summaryrefslogtreecommitdiffstats
path: root/chromium/content/shell/app/shell_main_mac.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/shell/app/shell_main_mac.cc')
-rw-r--r--chromium/content/shell/app/shell_main_mac.cc102
1 files changed, 102 insertions, 0 deletions
diff --git a/chromium/content/shell/app/shell_main_mac.cc b/chromium/content/shell/app/shell_main_mac.cc
new file mode 100644
index 00000000000..0097ce687a5
--- /dev/null
+++ b/chromium/content/shell/app/shell_main_mac.cc
@@ -0,0 +1,102 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <libgen.h>
+#include <mach-o/dyld.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+
+#include "base/allocator/early_zone_registration_mac.h"
+
+#if defined(HELPER_EXECUTABLE)
+#include "sandbox/mac/seatbelt_exec.h" // nogncheck
+#endif // defined(HELPER_EXECUTABLE)
+
+namespace {
+
+using ContentMainPtr = int (*)(int, char**);
+
+} // namespace
+
+int main(int argc, char* argv[]) {
+ partition_alloc::EarlyMallocZoneRegistration();
+
+ uint32_t exec_path_size = 0;
+ int rv = _NSGetExecutablePath(NULL, &exec_path_size);
+ if (rv != -1) {
+ fprintf(stderr, "_NSGetExecutablePath: get length failed\n");
+ abort();
+ }
+
+ std::unique_ptr<char[]> exec_path(new char[exec_path_size]);
+ rv = _NSGetExecutablePath(exec_path.get(), &exec_path_size);
+ if (rv != 0) {
+ fprintf(stderr, "_NSGetExecutablePath: get path failed\n");
+ abort();
+ }
+
+#if defined(HELPER_EXECUTABLE)
+ sandbox::SeatbeltExecServer::CreateFromArgumentsResult seatbelt =
+ sandbox::SeatbeltExecServer::CreateFromArguments(exec_path.get(), argc,
+ argv);
+ if (seatbelt.sandbox_required) {
+ if (!seatbelt.server) {
+ fprintf(stderr, "Failed to create seatbelt sandbox server.\n");
+ abort();
+ }
+ if (!seatbelt.server->InitializeSandbox()) {
+ fprintf(stderr, "Failed to initialize sandbox.\n");
+ abort();
+ }
+ }
+
+ // The Helper app is in the versioned framework directory, so just go up to
+ // the version folder to locate the dylib.
+ const char rel_path[] = "../../../../" SHELL_PRODUCT_NAME " Framework";
+#else
+ const char rel_path[] =
+ "../Frameworks/" SHELL_PRODUCT_NAME
+ " Framework.framework/" SHELL_PRODUCT_NAME " Framework";
+#endif // defined(HELPER_EXECUTABLE)
+
+ // Slice off the last part of the main executable path, and append the
+ // version framework information.
+ const char* parent_dir = dirname(exec_path.get());
+ if (!parent_dir) {
+ fprintf(stderr, "dirname %s: %s\n", exec_path.get(), strerror(errno));
+ abort();
+ }
+
+ const size_t parent_dir_len = strlen(parent_dir);
+ const size_t rel_path_len = strlen(rel_path);
+ // 2 accounts for a trailing NUL byte and the '/' in the middle of the paths.
+ const size_t framework_path_size = parent_dir_len + rel_path_len + 2;
+ std::unique_ptr<char[]> framework_path(new char[framework_path_size]);
+ snprintf(framework_path.get(), framework_path_size, "%s/%s", parent_dir,
+ rel_path);
+
+ void* library =
+ dlopen(framework_path.get(), RTLD_LAZY | RTLD_LOCAL | RTLD_FIRST);
+ if (!library) {
+ fprintf(stderr, "dlopen %s: %s\n", framework_path.get(), dlerror());
+ abort();
+ }
+
+ const ContentMainPtr content_main =
+ reinterpret_cast<ContentMainPtr>(dlsym(library, "ContentMain"));
+ if (!content_main) {
+ fprintf(stderr, "dlsym ContentMain: %s\n", dlerror());
+ abort();
+ }
+ rv = content_main(argc, argv);
+
+ // exit, don't return from main, to avoid the apparent removal of main from
+ // stack backtraces under tail call optimization.
+ exit(rv);
+}