Use content::Referrer to pass around referrers in the plugin code
[chromium-blink-merge.git] / chrome / browser / chrome_browser_main_posix.cc
bloba6f38b1da42e330dcc11a6bfd6008ce8d1b0ca0b
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/chrome_browser_main_posix.h"
7 #include <errno.h>
8 #include <limits.h>
9 #include <pthread.h>
10 #include <signal.h>
11 #include <sys/resource.h>
12 #include <unistd.h>
14 #include <string>
16 #include "base/bind.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/lifetime/application_lifetime.h"
23 #include "chrome/browser/sessions/session_restore.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/notification_observer.h"
27 #include "content/public/browser/notification_registrar.h"
28 #include "content/public/browser/notification_service.h"
30 using content::BrowserThread;
32 namespace {
34 // See comment in |PreEarlyInitialization()|, where sigaction is called.
35 void SIGCHLDHandler(int signal) {
38 // The OSX fork() implementation can crash in the child process before
39 // fork() returns. In that case, the shutdown pipe will still be
40 // shared with the parent process. To prevent child crashes from
41 // causing parent shutdowns, |g_pipe_pid| is the pid for the process
42 // which registered |g_shutdown_pipe_write_fd|.
43 // See <http://crbug.com/175341>.
44 pid_t g_pipe_pid = -1;
45 int g_shutdown_pipe_write_fd = -1;
46 int g_shutdown_pipe_read_fd = -1;
48 // Common code between SIG{HUP, INT, TERM}Handler.
49 void GracefulShutdownHandler(int signal) {
50 // Reinstall the default handler. We had one shot at graceful shutdown.
51 struct sigaction action;
52 memset(&action, 0, sizeof(action));
53 action.sa_handler = SIG_DFL;
54 RAW_CHECK(sigaction(signal, &action, NULL) == 0);
56 RAW_CHECK(g_pipe_pid == getpid());
57 RAW_CHECK(g_shutdown_pipe_write_fd != -1);
58 RAW_CHECK(g_shutdown_pipe_read_fd != -1);
59 size_t bytes_written = 0;
60 do {
61 int rv = HANDLE_EINTR(
62 write(g_shutdown_pipe_write_fd,
63 reinterpret_cast<const char*>(&signal) + bytes_written,
64 sizeof(signal) - bytes_written));
65 RAW_CHECK(rv >= 0);
66 bytes_written += rv;
67 } while (bytes_written < sizeof(signal));
70 // See comment in |PostMainMessageLoopStart()|, where sigaction is called.
71 void SIGHUPHandler(int signal) {
72 RAW_CHECK(signal == SIGHUP);
73 GracefulShutdownHandler(signal);
76 // See comment in |PostMainMessageLoopStart()|, where sigaction is called.
77 void SIGINTHandler(int signal) {
78 RAW_CHECK(signal == SIGINT);
79 GracefulShutdownHandler(signal);
82 // See comment in |PostMainMessageLoopStart()|, where sigaction is called.
83 void SIGTERMHandler(int signal) {
84 RAW_CHECK(signal == SIGTERM);
85 GracefulShutdownHandler(signal);
88 // ExitHandler takes care of servicing an exit (from a signal) at the
89 // appropriate time. Specifically if we get an exit and have not finished
90 // session restore we delay the exit. To do otherwise means we're exiting part
91 // way through startup which causes all sorts of problems.
92 class ExitHandler : public content::NotificationObserver {
93 public:
94 // Invokes exit when appropriate.
95 static void ExitWhenPossibleOnUIThread();
97 // Overridden from content::NotificationObserver:
98 void Observe(int type,
99 const content::NotificationSource& source,
100 const content::NotificationDetails& details) override;
102 private:
103 ExitHandler();
104 ~ExitHandler() override;
106 // Does the appropriate call to Exit.
107 static void Exit();
109 content::NotificationRegistrar registrar_;
111 DISALLOW_COPY_AND_ASSIGN(ExitHandler);
114 // static
115 void ExitHandler::ExitWhenPossibleOnUIThread() {
116 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
117 if (SessionRestore::IsRestoringSynchronously()) {
118 // ExitHandler takes care of deleting itself.
119 new ExitHandler();
120 } else {
121 Exit();
125 void ExitHandler::Observe(int type,
126 const content::NotificationSource& source,
127 const content::NotificationDetails& details) {
128 if (!SessionRestore::IsRestoringSynchronously()) {
129 // At this point the message loop may not be running (meaning we haven't
130 // gotten through browser startup, but are close). Post the task to at which
131 // point the message loop is running.
132 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
133 base::Bind(&ExitHandler::Exit));
134 delete this;
138 ExitHandler::ExitHandler() {
139 registrar_.Add(
140 this, chrome::NOTIFICATION_SESSION_RESTORE_DONE,
141 content::NotificationService::AllBrowserContextsAndSources());
144 ExitHandler::~ExitHandler() {
147 // static
148 void ExitHandler::Exit() {
149 #if defined(OS_CHROMEOS)
150 // On ChromeOS, exiting on signal should be always clean.
151 chrome::ExitCleanly();
152 #else
153 chrome::AttemptExit();
154 #endif
157 class ShutdownDetector : public base::PlatformThread::Delegate {
158 public:
159 explicit ShutdownDetector(int shutdown_fd);
161 void ThreadMain() override;
163 private:
164 const int shutdown_fd_;
166 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
169 ShutdownDetector::ShutdownDetector(int shutdown_fd)
170 : shutdown_fd_(shutdown_fd) {
171 CHECK_NE(shutdown_fd_, -1);
174 // These functions are used to help us diagnose crash dumps that happen
175 // during the shutdown process.
176 NOINLINE void ShutdownFDReadError() {
177 // Ensure function isn't optimized away.
178 asm("");
179 sleep(UINT_MAX);
182 NOINLINE void ShutdownFDClosedError() {
183 // Ensure function isn't optimized away.
184 asm("");
185 sleep(UINT_MAX);
188 NOINLINE void ExitPosted() {
189 // Ensure function isn't optimized away.
190 asm("");
191 sleep(UINT_MAX);
194 void ShutdownDetector::ThreadMain() {
195 base::PlatformThread::SetName("CrShutdownDetector");
197 int signal;
198 size_t bytes_read = 0;
199 ssize_t ret;
200 do {
201 ret = HANDLE_EINTR(
202 read(shutdown_fd_,
203 reinterpret_cast<char*>(&signal) + bytes_read,
204 sizeof(signal) - bytes_read));
205 if (ret < 0) {
206 NOTREACHED() << "Unexpected error: " << strerror(errno);
207 ShutdownFDReadError();
208 break;
209 } else if (ret == 0) {
210 NOTREACHED() << "Unexpected closure of shutdown pipe.";
211 ShutdownFDClosedError();
212 break;
214 bytes_read += ret;
215 } while (bytes_read < sizeof(signal));
216 VLOG(1) << "Handling shutdown for signal " << signal << ".";
217 base::Closure task = base::Bind(&ExitHandler::ExitWhenPossibleOnUIThread);
219 if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task)) {
220 // Without a UI thread to post the exit task to, there aren't many
221 // options. Raise the signal again. The default handler will pick it up
222 // and cause an ungraceful exit.
223 RAW_LOG(WARNING, "No UI thread, exiting ungracefully.");
224 kill(getpid(), signal);
226 // The signal may be handled on another thread. Give that a chance to
227 // happen.
228 sleep(3);
230 // We really should be dead by now. For whatever reason, we're not. Exit
231 // immediately, with the exit status set to the signal number with bit 8
232 // set. On the systems that we care about, this exit status is what is
233 // normally used to indicate an exit by this signal's default handler.
234 // This mechanism isn't a de jure standard, but even in the worst case, it
235 // should at least result in an immediate exit.
236 RAW_LOG(WARNING, "Still here, exiting really ungracefully.");
237 _exit(signal | (1 << 7));
239 ExitPosted();
242 } // namespace
244 // ChromeBrowserMainPartsPosix -------------------------------------------------
246 ChromeBrowserMainPartsPosix::ChromeBrowserMainPartsPosix(
247 const content::MainFunctionParams& parameters)
248 : ChromeBrowserMainParts(parameters) {
251 void ChromeBrowserMainPartsPosix::PreEarlyInitialization() {
252 ChromeBrowserMainParts::PreEarlyInitialization();
254 // We need to accept SIGCHLD, even though our handler is a no-op because
255 // otherwise we cannot wait on children. (According to POSIX 2001.)
256 struct sigaction action;
257 memset(&action, 0, sizeof(action));
258 action.sa_handler = SIGCHLDHandler;
259 CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
262 void ChromeBrowserMainPartsPosix::PostMainMessageLoopStart() {
263 ChromeBrowserMainParts::PostMainMessageLoopStart();
265 int pipefd[2];
266 int ret = pipe(pipefd);
267 if (ret < 0) {
268 PLOG(DFATAL) << "Failed to create pipe";
269 } else {
270 g_pipe_pid = getpid();
271 g_shutdown_pipe_read_fd = pipefd[0];
272 g_shutdown_pipe_write_fd = pipefd[1];
273 #if !defined(ADDRESS_SANITIZER) && !defined(KEEP_SHADOW_STACKS)
274 const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2;
275 #else
276 // ASan instrumentation and -finstrument-functions (used for keeping the
277 // shadow stacks) bloat the stack frames, so we need to increase the stack
278 // size to avoid hitting the guard page.
279 const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4;
280 #endif
281 // TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so
282 // if you change this, you'll probably need to change the suppression.
283 if (!base::PlatformThread::CreateNonJoinable(
284 kShutdownDetectorThreadStackSize,
285 new ShutdownDetector(g_shutdown_pipe_read_fd))) {
286 LOG(DFATAL) << "Failed to create shutdown detector task.";
289 // Setup signal handlers for shutdown AFTER shutdown pipe is setup because
290 // it may be called right away after handler is set.
292 // If adding to this list of signal handlers, note the new signal probably
293 // needs to be reset in child processes. See
294 // base/process_util_posix.cc:LaunchProcess.
296 // We need to handle SIGTERM, because that is how many POSIX-based distros ask
297 // processes to quit gracefully at shutdown time.
298 struct sigaction action;
299 memset(&action, 0, sizeof(action));
300 action.sa_handler = SIGTERMHandler;
301 CHECK(sigaction(SIGTERM, &action, NULL) == 0);
302 // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
303 // the browser process is being debugged, GDB will catch the SIGINT first.
304 action.sa_handler = SIGINTHandler;
305 CHECK(sigaction(SIGINT, &action, NULL) == 0);
306 // And SIGHUP, for when the terminal disappears. On shutdown, many Linux
307 // distros send SIGHUP, SIGTERM, and then SIGKILL.
308 action.sa_handler = SIGHUPHandler;
309 CHECK(sigaction(SIGHUP, &action, NULL) == 0);
312 void ChromeBrowserMainPartsPosix::ShowMissingLocaleMessageBox() {
313 #if defined(OS_CHROMEOS)
314 NOTREACHED(); // Should not ever happen on ChromeOS.
315 #elif defined(OS_MACOSX)
316 // Not called on Mac because we load the locale files differently.
317 NOTREACHED();
318 #elif defined(USE_AURA)
319 // TODO(port): We may want a views based message dialog here eventually, but
320 // for now, crash.
321 NOTREACHED();
322 #else
323 #error "Need MessageBox implementation."
324 #endif