• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
BrowserX11ErrorHandler(Display * d,XErrorEvent * error)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  
BrowserX11IOErrorHandler(Display * d)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  
PreEarlyInitialization()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  
DetectRunningAsRoot()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  
SetupSandbox()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  
DidEndMainMessageLoop()145  void DidEndMainMessageLoop() {
146  }
147  
RecordBreakpadStatusUMA(MetricsService * metrics)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  
WarnAboutMinimumSystemRequirements()157  void WarnAboutMinimumSystemRequirements() {
158    // Nothing to warn about on GTK right now.
159  }
160  
RecordBrowserStartupTime()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  
DoUninstallTasks(bool chrome_still_running)167  int DoUninstallTasks(bool chrome_still_running) {
168    return ResultCodes::NORMAL_EXIT;
169  }
170  
HandleIconsCommands(const CommandLine & parsed_command_line)171  int HandleIconsCommands(const CommandLine &parsed_command_line) {
172    return 0;
173  }
174  
CheckMachineLevelInstall()175  bool CheckMachineLevelInstall() {
176    return false;
177  }
178  
PrepareRestartOnCrashEnviroment(const CommandLine & parsed_command_line)179  void PrepareRestartOnCrashEnviroment(const CommandLine &parsed_command_line) {
180  }
181  
SetBrowserX11ErrorHandlers()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
CreateBrowserMainParts(const MainFunctionParams & parameters)190  BrowserMainParts* BrowserMainParts::CreateBrowserMainParts(
191      const MainFunctionParams& parameters) {
192    return new BrowserMainPartsGtk(parameters);
193  }
194  #endif
195