Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(466)

Side by Side Diff: chrome/renderer/renderer_main.cc

Issue 6878002: Move renderer_main and renderer_glue to content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/renderer/renderer_glue.cc ('k') | chrome/renderer/renderer_main_platform_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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.
4
5 #if defined(OS_MACOSX)
6 #include <signal.h>
7 #include <unistd.h>
8 #endif // OS_MACOSX
9
10 #include "base/command_line.h"
11 #include "base/debug/trace_event.h"
12 #include "base/i18n/rtl.h"
13 #include "base/mac/scoped_nsautorelease_pool.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/metrics/field_trial.h"
16 #include "base/message_loop.h"
17 #include "base/metrics/histogram.h"
18 #include "base/metrics/stats_counters.h"
19 #include "base/path_service.h"
20 #include "base/process_util.h"
21 #include "base/string_util.h"
22 #include "base/threading/platform_thread.h"
23 #include "base/time.h"
24 #include "chrome/common/chrome_constants.h"
25 #include "chrome/common/chrome_counters.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/logging_chrome.h"
28 #include "chrome/common/net/net_resource_provider.h"
29 #include "chrome/common/pepper_plugin_registry.h"
30 #include "chrome/renderer/renderer_main_platform_delegate.h"
31 #include "content/common/main_function_params.h"
32 #include "content/common/hi_res_timer_manager.h"
33 #include "content/renderer/render_process_impl.h"
34 #include "content/renderer/render_thread.h"
35 #include "grit/generated_resources.h"
36 #include "net/base/net_module.h"
37 #include "ui/base/system_monitor/system_monitor.h"
38 #include "ui/base/ui_base_switches.h"
39
40 #if defined(OS_MACOSX)
41 #include <Carbon/Carbon.h> // TISCreateInputSourceList
42
43 #include "base/eintr_wrapper.h"
44 #include "base/sys_info.h"
45 #include "chrome/app/breakpad_mac.h"
46 #include "third_party/mach_override/mach_override.h"
47 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
48 #endif // OS_MACOSX
49
50 #if defined(OS_MACOSX)
51 namespace {
52
53 CFArrayRef ChromeTISCreateInputSourceList(
54 CFDictionaryRef properties,
55 Boolean includeAllInstalled) {
56 CFTypeRef values[] = { CFSTR("") };
57 return CFArrayCreate(
58 kCFAllocatorDefault, values, arraysize(values), &kCFTypeArrayCallBacks);
59 }
60
61 void InstallFrameworkHacks() {
62 int32 os_major, os_minor, os_bugfix;
63 base::SysInfo::OperatingSystemVersionNumbers(
64 &os_major, &os_minor, &os_bugfix);
65
66 // See http://crbug.com/31225
67 // TODO: Don't do this on newer OS X revisions that have a fix for
68 // http://openradar.appspot.com/radar?id=1156410
69 if (os_major == 10 && os_minor >= 6) {
70 // Chinese Handwriting was introduced in 10.6. Since doing this override
71 // regresses page cycler memory usage on 10.5, don't do the unnecessary
72 // override there.
73 mach_error_t err = mach_override_ptr(
74 (void*)&TISCreateInputSourceList,
75 (void*)&ChromeTISCreateInputSourceList,
76 NULL);
77 CHECK_EQ(err_none, err);
78 }
79 }
80
81 // TODO(viettrungluu): crbug.com/28547: The following signal handling is needed,
82 // as a stopgap, to avoid leaking due to not releasing Breakpad properly.
83 // Without this problem, this could all be eliminated. Remove when Breakpad is
84 // fixed?
85 // TODO(viettrungluu): Code taken from browser_main.cc (with a bit of editing).
86 // The code should be properly shared (or this code should be eliminated).
87 int g_shutdown_pipe_write_fd = -1;
88
89 void SIGTERMHandler(int signal) {
90 RAW_CHECK(signal == SIGTERM);
91 RAW_LOG(INFO, "Handling SIGTERM in renderer.");
92
93 // Reinstall the default handler. We had one shot at graceful shutdown.
94 struct sigaction action;
95 memset(&action, 0, sizeof(action));
96 action.sa_handler = SIG_DFL;
97 CHECK(sigaction(signal, &action, NULL) == 0);
98
99 RAW_CHECK(g_shutdown_pipe_write_fd != -1);
100 size_t bytes_written = 0;
101 do {
102 int rv = HANDLE_EINTR(
103 write(g_shutdown_pipe_write_fd,
104 reinterpret_cast<const char*>(&signal) + bytes_written,
105 sizeof(signal) - bytes_written));
106 RAW_CHECK(rv >= 0);
107 bytes_written += rv;
108 } while (bytes_written < sizeof(signal));
109
110 RAW_LOG(INFO, "Wrote signal to shutdown pipe.");
111 }
112
113 class ShutdownDetector : public base::PlatformThread::Delegate {
114 public:
115 explicit ShutdownDetector(int shutdown_fd) : shutdown_fd_(shutdown_fd) {
116 CHECK(shutdown_fd_ != -1);
117 }
118
119 virtual void ThreadMain() {
120 int signal;
121 size_t bytes_read = 0;
122 ssize_t ret;
123 do {
124 ret = HANDLE_EINTR(
125 read(shutdown_fd_,
126 reinterpret_cast<char*>(&signal) + bytes_read,
127 sizeof(signal) - bytes_read));
128 if (ret < 0) {
129 NOTREACHED() << "Unexpected error: " << strerror(errno);
130 break;
131 } else if (ret == 0) {
132 NOTREACHED() << "Unexpected closure of shutdown pipe.";
133 break;
134 }
135 bytes_read += ret;
136 } while (bytes_read < sizeof(signal));
137
138 if (bytes_read == sizeof(signal))
139 VLOG(1) << "Handling shutdown for signal " << signal << ".";
140 else
141 VLOG(1) << "Handling shutdown for unknown signal.";
142
143 // Clean up Breakpad if necessary.
144 if (IsCrashReporterEnabled()) {
145 VLOG(1) << "Cleaning up Breakpad.";
146 DestructCrashReporter();
147 } else {
148 VLOG(1) << "Breakpad not enabled; no clean-up needed.";
149 }
150
151 // Something went seriously wrong, so get out.
152 if (bytes_read != sizeof(signal)) {
153 LOG(WARNING) << "Failed to get signal. Quitting ungracefully.";
154 _exit(1);
155 }
156
157 // Re-raise the signal.
158 kill(getpid(), signal);
159
160 // The signal may be handled on another thread. Give that a chance to
161 // happen.
162 sleep(3);
163
164 // We really should be dead by now. For whatever reason, we're not. Exit
165 // immediately, with the exit status set to the signal number with bit 8
166 // set. On the systems that we care about, this exit status is what is
167 // normally used to indicate an exit by this signal's default handler.
168 // This mechanism isn't a de jure standard, but even in the worst case, it
169 // should at least result in an immediate exit.
170 LOG(WARNING) << "Still here, exiting really ungracefully.";
171 _exit(signal | (1 << 7));
172 }
173
174 private:
175 const int shutdown_fd_;
176
177 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
178 };
179
180 } // namespace
181 #endif // OS_MACOSX
182
183 // This function provides some ways to test crash and assertion handling
184 // behavior of the renderer.
185 static void HandleRendererErrorTestParameters(const CommandLine& command_line) {
186 // This parameter causes an assertion.
187 if (command_line.HasSwitch(switches::kRendererAssertTest)) {
188 DCHECK(false);
189 }
190
191
192 #if !defined(OFFICIAL_BUILD)
193 // This parameter causes an assertion too.
194 if (command_line.HasSwitch(switches::kRendererCheckFalseTest)) {
195 CHECK(false);
196 }
197 #endif // !defined(OFFICIAL_BUILD)
198
199
200 // This parameter causes a null pointer crash (crash reporter trigger).
201 if (command_line.HasSwitch(switches::kRendererCrashTest)) {
202 int* bad_pointer = NULL;
203 *bad_pointer = 0;
204 }
205
206 if (command_line.HasSwitch(switches::kRendererStartupDialog)) {
207 ChildProcess::WaitForDebugger("Renderer");
208 }
209 }
210
211 // This is a simplified version of the browser Jankometer, which measures
212 // the processing time of tasks on the render thread.
213 class RendererMessageLoopObserver : public MessageLoop::TaskObserver {
214 public:
215 RendererMessageLoopObserver()
216 : process_times_(base::Histogram::FactoryGet(
217 "Chrome.ProcMsgL RenderThread",
218 1, 3600000, 50, base::Histogram::kUmaTargetedHistogramFlag)) {}
219 virtual ~RendererMessageLoopObserver() {}
220
221 virtual void WillProcessTask(const Task* task) {
222 begin_process_message_ = base::TimeTicks::Now();
223 }
224
225 virtual void DidProcessTask(const Task* task) {
226 if (begin_process_message_ != base::TimeTicks())
227 process_times_->AddTime(base::TimeTicks::Now() - begin_process_message_);
228 }
229
230 private:
231 base::TimeTicks begin_process_message_;
232 base::Histogram* const process_times_;
233 DISALLOW_COPY_AND_ASSIGN(RendererMessageLoopObserver);
234 };
235
236 // mainline routine for running as the Renderer process
237 int RendererMain(const MainFunctionParams& parameters) {
238 TRACE_EVENT_BEGIN("RendererMain", 0, "");
239
240 const CommandLine& parsed_command_line = parameters.command_line_;
241 base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool_;
242
243 #if defined(OS_MACOSX)
244 // TODO(viettrungluu): Code taken from browser_main.cc.
245 int pipefd[2];
246 int ret = pipe(pipefd);
247 if (ret < 0) {
248 PLOG(DFATAL) << "Failed to create pipe";
249 } else {
250 int shutdown_pipe_read_fd = pipefd[0];
251 g_shutdown_pipe_write_fd = pipefd[1];
252 const size_t kShutdownDetectorThreadStackSize = 4096;
253 if (!base::PlatformThread::CreateNonJoinable(
254 kShutdownDetectorThreadStackSize,
255 new ShutdownDetector(shutdown_pipe_read_fd))) {
256 LOG(DFATAL) << "Failed to create shutdown detector task.";
257 }
258 }
259
260 // crbug.com/28547: When Breakpad is in use, handle SIGTERM to avoid leaking
261 // Mach ports.
262 struct sigaction action;
263 memset(&action, 0, sizeof(action));
264 action.sa_handler = SIGTERMHandler;
265 CHECK(sigaction(SIGTERM, &action, NULL) == 0);
266
267 InstallFrameworkHacks();
268 #endif // OS_MACOSX
269
270 #if defined(OS_CHROMEOS)
271 // As Zygote process starts up earlier than browser process gets its own
272 // locale (at login time for Chrome OS), we have to set the ICU default
273 // locale for renderer process here.
274 // ICU locale will be used for fallback font selection etc.
275 if (parsed_command_line.HasSwitch(switches::kLang)) {
276 const std::string locale =
277 parsed_command_line.GetSwitchValueASCII(switches::kLang);
278 base::i18n::SetICUDefaultLocale(locale);
279 }
280 #endif
281
282 // Configure modules that need access to resources.
283 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
284
285 // This function allows pausing execution using the --renderer-startup-dialog
286 // flag allowing us to attach a debugger.
287 // Do not move this function down since that would mean we can't easily debug
288 // whatever occurs before it.
289 HandleRendererErrorTestParameters(parsed_command_line);
290
291 RendererMainPlatformDelegate platform(parameters);
292
293 base::StatsScope<base::StatsCounterTimer>
294 startup_timer(chrome::Counters::renderer_main());
295
296 RendererMessageLoopObserver task_observer;
297 #if defined(OS_MACOSX)
298 // As long as we use Cocoa in the renderer (for the forseeable future as of
299 // now; see http://crbug.com/13890 for info) we need to have a UI loop.
300 MessageLoop main_message_loop(MessageLoop::TYPE_UI);
301 #else
302 // The main message loop of the renderer services doesn't have IO or UI tasks,
303 // unless in-process-plugins is used.
304 MessageLoop main_message_loop(RenderProcessImpl::InProcessPlugins() ?
305 MessageLoop::TYPE_UI : MessageLoop::TYPE_DEFAULT);
306 #endif
307 main_message_loop.AddTaskObserver(&task_observer);
308
309 base::PlatformThread::SetName("CrRendererMain");
310
311 ui::SystemMonitor system_monitor;
312 HighResolutionTimerManager hi_res_timer_manager;
313
314 platform.PlatformInitialize();
315
316 bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox);
317 platform.InitSandboxTests(no_sandbox);
318
319 // Initialize histogram statistics gathering system.
320 // Don't create StatisticsRecorder in the single process mode.
321 scoped_ptr<base::StatisticsRecorder> statistics;
322 if (!base::StatisticsRecorder::IsActive()) {
323 statistics.reset(new base::StatisticsRecorder());
324 }
325
326 // Initialize statistical testing infrastructure.
327 base::FieldTrialList field_trial;
328 // Ensure any field trials in browser are reflected into renderer.
329 if (parsed_command_line.HasSwitch(switches::kForceFieldTestNameAndValue)) {
330 std::string persistent = parsed_command_line.GetSwitchValueASCII(
331 switches::kForceFieldTestNameAndValue);
332 bool ret = field_trial.CreateTrialsInChildProcess(persistent);
333 DCHECK(ret);
334 }
335
336 // Load pepper plugins before engaging the sandbox.
337 PepperPluginRegistry::GetInstance();
338
339 {
340 #if !defined(OS_LINUX)
341 // TODO(markus): Check if it is OK to unconditionally move this
342 // instruction down.
343 RenderProcessImpl render_process;
344 render_process.set_main_thread(new RenderThread());
345 #endif
346 bool run_loop = true;
347 if (!no_sandbox) {
348 run_loop = platform.EnableSandbox();
349 } else {
350 LOG(ERROR) << "Running without renderer sandbox";
351 }
352 #if defined(OS_LINUX)
353 RenderProcessImpl render_process;
354 render_process.set_main_thread(new RenderThread());
355 #endif
356
357 platform.RunSandboxTests();
358
359 startup_timer.Stop(); // End of Startup Time Measurement.
360
361 if (run_loop) {
362 if (pool)
363 pool->Recycle();
364 TRACE_EVENT_BEGIN("RendererMain.START_MSG_LOOP", 0, 0);
365 MessageLoop::current()->Run();
366 TRACE_EVENT_END("RendererMain.START_MSG_LOOP", 0, 0);
367 }
368 }
369 platform.PlatformUninitialize();
370 TRACE_EVENT_END("RendererMain", 0, "");
371 return 0;
372 }
OLDNEW
« no previous file with comments | « chrome/renderer/renderer_glue.cc ('k') | chrome/renderer/renderer_main_platform_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698