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 37 namespace { 38 39 // Indicates that we're currently responding to an IO error (by shutting down). 40 bool g_in_x11_io_error_handler = false; 41 42 int 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 50 int 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 63 void 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 76 void 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 117 void 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 145 void DidEndMainMessageLoop() { 146 } 147 148 void 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 157 void WarnAboutMinimumSystemRequirements() { 158 // Nothing to warn about on GTK right now. 159 } 160 161 void 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 167 int DoUninstallTasks(bool chrome_still_running) { 168 return ResultCodes::NORMAL_EXIT; 169 } 170 171 int HandleIconsCommands(const CommandLine &parsed_command_line) { 172 return 0; 173 } 174 175 bool CheckMachineLevelInstall() { 176 return false; 177 } 178 179 void PrepareRestartOnCrashEnviroment(const CommandLine &parsed_command_line) { 180 } 181 182 void 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 190 BrowserMainParts* BrowserMainParts::CreateBrowserMainParts( 191 const MainFunctionParams& parameters) { 192 return new BrowserMainPartsGtk(parameters); 193 } 194 #endif 195