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#include "chrome/browser/browser_main_gtk.h" 6 7#include <gtk/gtk.h> 8#include <sys/stat.h> 9#include <sys/types.h> 10#include <unistd.h> 11 12#include "base/command_line.h" 13#include "base/debug/debugger.h" 14#include "chrome/browser/browser_main_win.h" 15#include "chrome/browser/metrics/metrics_service.h" 16#include "chrome/browser/ui/browser_list.h" 17#include "chrome/common/chrome_switches.h" 18#include "content/browser/renderer_host/render_sandbox_host_linux.h" 19#include "content/browser/zygote_host_linux.h" 20#include "content/common/result_codes.h" 21#include "grit/chromium_strings.h" 22#include "grit/generated_resources.h" 23#include "ui/base/l10n/l10n_util.h" 24#include "ui/base/resource/resource_bundle.h" 25#include "ui/base/x/x11_util.h" 26#include "ui/base/x/x11_util_internal.h" 27#include "ui/gfx/gtk_util.h" 28 29#if defined(USE_NSS) 30#include "crypto/nss_util.h" 31#endif 32 33#if defined(USE_LINUX_BREAKPAD) 34#include "chrome/app/breakpad_linux.h" 35#endif 36 37namespace { 38 39// Indicates that we're currently responding to an IO error (by shutting down). 40bool g_in_x11_io_error_handler = false; 41 42int BrowserX11ErrorHandler(Display* d, XErrorEvent* error) { 43 if (!g_in_x11_io_error_handler) 44 MessageLoop::current()->PostTask( 45 FROM_HERE, 46 NewRunnableFunction(ui::LogErrorEventDescription, d, *error)); 47 return 0; 48} 49 50int BrowserX11IOErrorHandler(Display* d) { 51 // If there's an IO error it likely means the X server has gone away 52 if (!g_in_x11_io_error_handler) { 53 g_in_x11_io_error_handler = true; 54 LOG(ERROR) << "X IO Error detected"; 55 BrowserList::SessionEnding(); 56 } 57 58 return 0; 59} 60 61} // namespace 62 63void BrowserMainPartsGtk::PreEarlyInitialization() { 64 DetectRunningAsRoot(); 65 66 BrowserMainPartsPosix::PreEarlyInitialization(); 67 68 SetupSandbox(); 69 70#if defined(USE_NSS) 71 // We want to be sure to init NSPR on the main thread. 72 crypto::EnsureNSPRInit(); 73#endif 74} 75 76void BrowserMainPartsGtk::DetectRunningAsRoot() { 77 if (geteuid() == 0) { 78 const CommandLine& command_line = *CommandLine::ForCurrentProcess(); 79 if (!parsed_command_line().HasSwitch(switches::kUserDataDir)) 80 return; 81 82 gfx::GtkInitFromCommandLine(command_line); 83 84 // Get just enough of our resource machinery up so we can extract the 85 // locale appropriate string. Note that the GTK implementation ignores the 86 // passed in parameter and checks the LANG environment variables instead. 87 ResourceBundle::InitSharedInstance(""); 88 89 std::string message = l10n_util::GetStringFUTF8( 90 IDS_REFUSE_TO_RUN_AS_ROOT, 91 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 92 GtkWidget* dialog = gtk_message_dialog_new( 93 NULL, 94 static_cast<GtkDialogFlags>(0), 95 GTK_MESSAGE_ERROR, 96 GTK_BUTTONS_CLOSE, 97 "%s", 98 message.c_str()); 99 100 LOG(ERROR) << "Startup refusing to run as root."; 101 message = l10n_util::GetStringFUTF8( 102 IDS_REFUSE_TO_RUN_AS_ROOT_2, 103 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 104 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 105 "%s", 106 message.c_str()); 107 108 message = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME); 109 gtk_window_set_title(GTK_WINDOW(dialog), message.c_str()); 110 111 gtk_dialog_run(GTK_DIALOG(dialog)); 112 gtk_widget_destroy(dialog); 113 exit(EXIT_FAILURE); 114 } 115} 116 117void BrowserMainPartsGtk::SetupSandbox() { 118 // TODO(evanm): move this into SandboxWrapper; I'm just trying to move this 119 // code en masse out of chrome_main for now. 120 const char* sandbox_binary = NULL; 121 struct stat st; 122 123 // In Chromium branded builds, developers can set an environment variable to 124 // use the development sandbox. See 125 // http://code.google.com/p/chromium/wiki/LinuxSUIDSandboxDevelopment 126 if (stat("/proc/self/exe", &st) == 0 && st.st_uid == getuid()) 127 sandbox_binary = getenv("CHROME_DEVEL_SANDBOX"); 128 129#if defined(LINUX_SANDBOX_PATH) 130 if (!sandbox_binary) 131 sandbox_binary = LINUX_SANDBOX_PATH; 132#endif 133 134 std::string sandbox_cmd; 135 if (sandbox_binary && !parsed_command_line().HasSwitch(switches::kNoSandbox)) 136 sandbox_cmd = sandbox_binary; 137 138 // Tickle the sandbox host and zygote host so they fork now. 139 RenderSandboxHostLinux* shost = RenderSandboxHostLinux::GetInstance(); 140 shost->Init(sandbox_cmd); 141 ZygoteHost* zhost = ZygoteHost::GetInstance(); 142 zhost->Init(sandbox_cmd); 143} 144 145void DidEndMainMessageLoop() { 146} 147 148void RecordBreakpadStatusUMA(MetricsService* metrics) { 149#if defined(USE_LINUX_BREAKPAD) 150 metrics->RecordBreakpadRegistration(IsCrashReporterEnabled()); 151#else 152 metrics->RecordBreakpadRegistration(false); 153#endif 154 metrics->RecordBreakpadHasDebugger(base::debug::BeingDebugged()); 155} 156 157void WarnAboutMinimumSystemRequirements() { 158 // Nothing to warn about on GTK right now. 159} 160 161void RecordBrowserStartupTime() { 162 // Not implemented on GTK for now. 163} 164 165// From browser_main_win.h, stubs until we figure out the right thing... 166 167int DoUninstallTasks(bool chrome_still_running) { 168 return ResultCodes::NORMAL_EXIT; 169} 170 171int HandleIconsCommands(const CommandLine &parsed_command_line) { 172 return 0; 173} 174 175bool CheckMachineLevelInstall() { 176 return false; 177} 178 179void PrepareRestartOnCrashEnviroment(const CommandLine &parsed_command_line) { 180} 181 182void SetBrowserX11ErrorHandlers() { 183 // Set up error handlers to make sure profile gets written if X server 184 // goes away. 185 ui::SetX11ErrorHandlers(BrowserX11ErrorHandler, BrowserX11IOErrorHandler); 186} 187 188#if !defined(OS_CHROMEOS) 189// static 190BrowserMainParts* BrowserMainParts::CreateBrowserMainParts( 191 const MainFunctionParams& parameters) { 192 return new BrowserMainPartsGtk(parameters); 193} 194#endif 195