diff options
Diffstat (limited to 'chromium/content/shell/app/shell_main_mac.cc')
-rw-r--r-- | chromium/content/shell/app/shell_main_mac.cc | 102 |
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); +} |