diff options
Diffstat (limited to 'chromium/content/shell/app')
19 files changed, 1305 insertions, 0 deletions
diff --git a/chromium/content/shell/app/DEPS b/chromium/content/shell/app/DEPS new file mode 100644 index 00000000000..f64b894c822 --- /dev/null +++ b/chromium/content/shell/app/DEPS @@ -0,0 +1,11 @@ +include_rules = [ +] + +specific_include_rules = { + "shell_main_delegate\.cc": [ + # Separating Content Shell and web test code. ShellMainDelegate injects web test + # code into Content Shell at runtime. + "+content/web_test/browser", + "+content/web_test/renderer", + ], +} diff --git a/chromium/content/shell/app/app-Info.plist b/chromium/content/shell/app/app-Info.plist new file mode 100644 index 00000000000..65b019e3e2b --- /dev/null +++ b/chromium/content/shell/app/app-Info.plist @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string>app.icns</string> + <key>CFBundleIdentifier</key> + <string>org.chromium.ContentShell</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> + <key>LSFileQuarantineEnabled</key> + <true/> + <key>NSSupportsAutomaticGraphicsSwitching</key> + <true/> + <key>NSBluetoothAlwaysUsageDescription</key> + <string>Content Shell may use Bluetooth to implement Web Platform features.</string> +</dict> +</plist> diff --git a/chromium/content/shell/app/app.icns b/chromium/content/shell/app/app.icns Binary files differnew file mode 100644 index 00000000000..f36742de257 --- /dev/null +++ b/chromium/content/shell/app/app.icns diff --git a/chromium/content/shell/app/framework-Info.plist b/chromium/content/shell/app/framework-Info.plist new file mode 100644 index 00000000000..ee19476052d --- /dev/null +++ b/chromium/content/shell/app/framework-Info.plist @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>org.chromium.ContentShell.framework</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleSignature</key> + <string>????</string> +</dict> +</plist> diff --git a/chromium/content/shell/app/helper-Info.plist b/chromium/content/shell/app/helper-Info.plist new file mode 100644 index 00000000000..2503b29efca --- /dev/null +++ b/chromium/content/shell/app/helper-Info.plist @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>en</string> + <key>CFBundleDisplayName</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIdentifier</key> + <string>org.chromium.ContentShell.helper${CONTENT_SHELL_HELPER_BUNDLE_ID_SUFFIX}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>LSFileQuarantineEnabled</key> + <true/> + <key>LSUIElement</key> + <string>1</string> + <key>NSSupportsAutomaticGraphicsSwitching</key> + <true/> +</dict> +</plist> diff --git a/chromium/content/shell/app/paths_mac.h b/chromium/content/shell/app/paths_mac.h new file mode 100644 index 00000000000..e704128cfee --- /dev/null +++ b/chromium/content/shell/app/paths_mac.h @@ -0,0 +1,30 @@ +// Copyright 2013 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. + +#ifndef CONTENT_SHELL_APP_PATHS_MAC_H_ +#define CONTENT_SHELL_APP_PATHS_MAC_H_ + +namespace base { +class FilePath; +} + +// Sets up base::mac::FrameworkBundle. +void OverrideFrameworkBundlePath(); + +// Set up base::mac::OuterBundle. +void OverrideOuterBundlePath(); + +// Sets up the CHILD_PROCESS_EXE path to properly point to the helper app. +void OverrideChildProcessPath(); + +// Sets up base::DIR_SOURCE_ROOT to properly point to the source directory. +void OverrideSourceRootPath(); + +// Gets the path to the content shell's pak file. +base::FilePath GetResourcesPakFilePath(); + +// Gets the path to content shell's Info.plist file. +base::FilePath GetInfoPlistPath(); + +#endif // CONTENT_SHELL_APP_PATHS_MAC_H_ diff --git a/chromium/content/shell/app/paths_mac.mm b/chromium/content/shell/app/paths_mac.mm new file mode 100644 index 00000000000..c43cb6cadda --- /dev/null +++ b/chromium/content/shell/app/paths_mac.mm @@ -0,0 +1,96 @@ +// Copyright 2013 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 "content/shell/app/paths_mac.h" + +#include "base/base_paths.h" +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#include "base/path_service.h" +#include "content/public/common/content_paths.h" + +namespace { + +base::FilePath GetContentsPath() { + // Start out with the path to the running executable. + base::FilePath path; + base::PathService::Get(base::FILE_EXE, &path); + + // Up to Contents. + if (base::mac::IsBackgroundOnlyProcess()) { + // The running executable is the helper, located at: + // Content Shell.app/Contents/Frameworks/ + // Content Shell Framework.framework/Versions/C/Helpers/Content Shell + // Helper.app/ Contents/MacOS/Content Shell Helper. Go up nine steps to get + // to the main bundle's Contents directory. + path = path.DirName() + .DirName() + .DirName() + .DirName() + .DirName() + .DirName() + .DirName() + .DirName() + .DirName(); + } else { + // One step up to MacOS, another to Contents. + path = path.DirName().DirName(); + } + DCHECK_EQ("Contents", path.BaseName().value()); + + return path; +} + +base::FilePath GetFrameworksPath() { + return GetContentsPath().Append("Frameworks"); +} + +} // namespace + +void OverrideFrameworkBundlePath() { + base::FilePath helper_path = + GetFrameworksPath().Append("Content Shell Framework.framework"); + + base::mac::SetOverrideFrameworkBundlePath(helper_path); +} + +void OverrideOuterBundlePath() { + base::FilePath path = GetContentsPath().DirName(); + + base::mac::SetOverrideOuterBundlePath(path); +} + +void OverrideChildProcessPath() { + base::FilePath helper_path = base::mac::FrameworkBundlePath() + .Append("Helpers") + .Append("Content Shell Helper.app") + .Append("Contents") + .Append("MacOS") + .Append("Content Shell Helper"); + + base::PathService::Override(content::CHILD_PROCESS_EXE, helper_path); +} + +void OverrideSourceRootPath() { + // The base implementation to get base::DIR_SOURCE_ROOT assumes the current + // process path is the top level app path, not a nested one. + // + // Going up 5 levels is needed, since frameworks path looks something like + // src/out/foo/Content Shell.app/Contents/Framework/ + base::PathService::Override( + base::DIR_SOURCE_ROOT, + GetFrameworksPath().DirName().DirName().DirName().DirName().DirName()); +} + +base::FilePath GetResourcesPakFilePath() { + NSString* pak_path = + [base::mac::FrameworkBundle() pathForResource:@"content_shell" + ofType:@"pak"]; + + return base::FilePath([pak_path fileSystemRepresentation]); +} + +base::FilePath GetInfoPlistPath() { + return GetContentsPath().Append("Info.plist"); +} diff --git a/chromium/content/shell/app/resource.h b/chromium/content/shell/app/resource.h new file mode 100644 index 00000000000..29bb74dfa78 --- /dev/null +++ b/chromium/content/shell/app/resource.h @@ -0,0 +1,41 @@ +// Copyright (c) 2012 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. + +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by test_shell.rc +// + + +#define IDR_MAINFRAME 128 +#define IDM_EXIT 105 +#define IDM_CLOSE_WINDOW 106 +#define IDM_NEW_WINDOW 107 +#define IDM_SHOW_DEVELOPER_TOOLS 108 +#define IDC_CONTENTSHELL 109 +#define IDD_ALERT 130 +#define IDD_CONFIRM 131 +#define IDD_PROMPT 132 +#define IDC_NAV_BACK 1001 +#define IDC_NAV_FORWARD 1002 +#define IDC_NAV_RELOAD 1003 +#define IDC_NAV_STOP 1004 +#define IDC_PROMPTEDIT 1005 +#define IDC_DIALOGTEXT 1006 + +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 117 +#endif +#endif diff --git a/chromium/content/shell/app/shell.rc b/chromium/content/shell/app/shell.rc new file mode 100644 index 00000000000..2987c067570 --- /dev/null +++ b/chromium/content/shell/app/shell.rc @@ -0,0 +1,146 @@ +//Microsoft Visual C++ generated resource script. +// +#include "content/shell/app/resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#define APSTUDIO_HIDDEN_SYMBOLS +#include "windows.h" +#undef APSTUDIO_HIDDEN_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE 9, 1 +#pragma code_page(1252) + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDC_CONTENTSHELL MENU +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&New Window", IDM_NEW_WINDOW + MENUITEM "&Close Window", IDM_CLOSE_WINDOW + MENUITEM "E&xit", IDM_EXIT + END + POPUP "&Debug" + BEGIN + MENUITEM "&Show Developer Tools...", IDM_SHOW_DEVELOPER_TOOLS + END +END + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ALERT DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Alert" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,184,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,30 +END + +IDD_CONFIRM DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Confirm" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14 + DEFPUSHBUTTON "OK",IDOK,131,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,30 +END + +IDD_PROMPT DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Prompt" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,131,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,18 + PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14 + EDITTEXT IDC_PROMPTEDIT,15,33,210,14,ES_AUTOHSCROLL +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_ALERT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 234 + TOPMARGIN, 7 + BOTTOMMARGIN, 69 + END + + IDD_CONFIRM, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 234 + TOPMARGIN, 7 + BOTTOMMARGIN, 69 + END + + IDD_PROMPT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 234 + TOPMARGIN, 7 + BOTTOMMARGIN, 69 + END +END +#endif // APSTUDIO_INVOKED + +#endif +///////////////////////////////////////////////////////////////////////////// + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/chromium/content/shell/app/shell_content_main.cc b/chromium/content/shell/app/shell_content_main.cc new file mode 100644 index 00000000000..fc0caafbea8 --- /dev/null +++ b/chromium/content/shell/app/shell_content_main.cc @@ -0,0 +1,29 @@ +// Copyright 2013 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 "content/shell/app/shell_content_main.h" + +#include "build/build_config.h" +#include "content/public/app/content_main.h" +#include "content/public/common/content_switches.h" +#include "content/shell/app/shell_main_delegate.h" + +#if BUILDFLAG(IS_MAC) +int ContentMain(int argc, + const char** argv) { + bool is_browsertest = false; + std::string browser_test_flag(std::string("--") + switches::kBrowserTest); + for (int i = 0; i < argc; ++i) { + if (browser_test_flag == argv[i]) { + is_browsertest = true; + break; + } + } + content::ShellMainDelegate delegate(is_browsertest); + content::ContentMainParams params(&delegate); + params.argc = argc; + params.argv = argv; + return content::ContentMain(std::move(params)); +} +#endif // BUILDFLAG(IS_MAC) diff --git a/chromium/content/shell/app/shell_content_main.h b/chromium/content/shell/app/shell_content_main.h new file mode 100644 index 00000000000..58bcbab9a1a --- /dev/null +++ b/chromium/content/shell/app/shell_content_main.h @@ -0,0 +1,18 @@ +// Copyright 2013 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. + +#ifndef CONTENT_SHELL_APP_SHELL_CONTENT_MAIN_H_ +#define CONTENT_SHELL_APP_SHELL_CONTENT_MAIN_H_ + +#include "build/build_config.h" + +#if BUILDFLAG(IS_MAC) +extern "C" { +__attribute__((visibility("default"))) +int ContentMain(int argc, + const char** argv); +} // extern "C" +#endif // BUILDFLAG(IS_MAC) + +#endif // CONTENT_SHELL_APP_SHELL_CONTENT_MAIN_H_ diff --git a/chromium/content/shell/app/shell_crash_reporter_client.cc b/chromium/content/shell/app/shell_crash_reporter_client.cc new file mode 100644 index 00000000000..4c76c176753 --- /dev/null +++ b/chromium/content/shell/app/shell_crash_reporter_client.cc @@ -0,0 +1,95 @@ +// Copyright 2013 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 "content/shell/app/shell_crash_reporter_client.h" + +#include <string> +#include <utility> + +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" +#include "content/public/common/content_switches.h" +#include "content/shell/common/shell_switches.h" + +#if BUILDFLAG(IS_ANDROID) +#include "content/shell/android/shell_descriptors.h" +#endif + +namespace content { + +ShellCrashReporterClient::ShellCrashReporterClient() {} +ShellCrashReporterClient::~ShellCrashReporterClient() {} + +#if BUILDFLAG(IS_WIN) +void ShellCrashReporterClient::GetProductNameAndVersion( + const std::wstring& exe_path, + std::wstring* product_name, + std::wstring* version, + std::wstring* special_build, + std::wstring* channel_name) { + *product_name = L"content_shell"; + *version = base::ASCIIToWide(CONTENT_SHELL_VERSION); + *special_build = std::wstring(); + *channel_name = std::wstring(); +} +#endif + +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) +void ShellCrashReporterClient::GetProductNameAndVersion( + const char** product_name, + const char** version) { + *product_name = "content_shell"; + *version = CONTENT_SHELL_VERSION; +} + +void ShellCrashReporterClient::GetProductNameAndVersion( + std::string* product_name, + std::string* version, + std::string* channel) { + *product_name = "content_shell"; + *version = CONTENT_SHELL_VERSION; + *channel = ""; +} + +base::FilePath ShellCrashReporterClient::GetReporterLogFilename() { + return base::FilePath(FILE_PATH_LITERAL("uploads.log")); +} +#endif + +#if BUILDFLAG(IS_WIN) +bool ShellCrashReporterClient::GetCrashDumpLocation(std::wstring* crash_dir) { +#else +bool ShellCrashReporterClient::GetCrashDumpLocation(base::FilePath* crash_dir) { +#endif + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kCrashDumpsDir)) + return false; + base::FilePath crash_directory = + base::CommandLine::ForCurrentProcess()->GetSwitchValuePath( + switches::kCrashDumpsDir); +#if BUILDFLAG(IS_WIN) + *crash_dir = crash_directory.value(); +#else + *crash_dir = std::move(crash_directory); +#endif + return true; +} + +#if BUILDFLAG(IS_ANDROID) +int ShellCrashReporterClient::GetAndroidMinidumpDescriptor() { + return kAndroidMinidumpDescriptor; +} +#endif + +bool ShellCrashReporterClient::EnableBreakpadForProcess( + const std::string& process_type) { + return process_type == switches::kRendererProcess || + process_type == switches::kPpapiPluginProcess || + process_type == switches::kZygoteProcess || + process_type == switches::kGpuProcess; +} + +} // namespace content diff --git a/chromium/content/shell/app/shell_crash_reporter_client.h b/chromium/content/shell/app/shell_crash_reporter_client.h new file mode 100644 index 00000000000..3eb37a61932 --- /dev/null +++ b/chromium/content/shell/app/shell_crash_reporter_client.h @@ -0,0 +1,61 @@ +// Copyright 2013 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. + +#ifndef CONTENT_SHELL_APP_SHELL_CRASH_REPORTER_CLIENT_H_ +#define CONTENT_SHELL_APP_SHELL_CRASH_REPORTER_CLIENT_H_ + +#include "build/build_config.h" +#include "components/crash/core/app/crash_reporter_client.h" + +namespace content { + +class ShellCrashReporterClient : public crash_reporter::CrashReporterClient { + public: + ShellCrashReporterClient(); + + ShellCrashReporterClient(const ShellCrashReporterClient&) = delete; + ShellCrashReporterClient& operator=(const ShellCrashReporterClient&) = delete; + + ~ShellCrashReporterClient() override; + +#if BUILDFLAG(IS_WIN) + // Returns a textual description of the product type and version to include + // in the crash report. + void GetProductNameAndVersion(const std::wstring& exe_path, + std::wstring* product_name, + std::wstring* version, + std::wstring* special_build, + std::wstring* channel_name) override; +#endif + +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) + // Returns a textual description of the product type and version to include + // in the crash report. + void GetProductNameAndVersion(const char** product_name, + const char** version) override; + void GetProductNameAndVersion(std::string* product_name, + std::string* version, + std::string* channel) override; + base::FilePath GetReporterLogFilename() override; +#endif + + // The location where minidump files should be written. Returns true if + // |crash_dir| was set. +#if BUILDFLAG(IS_WIN) + bool GetCrashDumpLocation(std::wstring* crash_dir) override; +#else + bool GetCrashDumpLocation(base::FilePath* crash_dir) override; +#endif + +#if BUILDFLAG(IS_ANDROID) + // Returns the descriptor key of the android minidump global descriptor. + int GetAndroidMinidumpDescriptor() override; +#endif + + bool EnableBreakpadForProcess(const std::string& process_type) override; +}; + +} // namespace content + +#endif // CONTENT_SHELL_APP_SHELL_CRASH_REPORTER_CLIENT_H_ diff --git a/chromium/content/shell/app/shell_main.cc b/chromium/content/shell/app/shell_main.cc new file mode 100644 index 00000000000..421a4857d2d --- /dev/null +++ b/chromium/content/shell/app/shell_main.cc @@ -0,0 +1,46 @@ +// Copyright (c) 2012 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 "build/build_config.h" +#include "content/public/app/content_main.h" +#include "content/shell/app/shell_main_delegate.h" + +#if BUILDFLAG(IS_WIN) +#include "base/win/win_util.h" +#include "content/public/app/sandbox_helper_win.h" +#include "sandbox/win/src/sandbox_types.h" +#endif + +#if BUILDFLAG(IS_WIN) + +#if !defined(WIN_CONSOLE_APP) +int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t*, int) { +#else +int main() { + HINSTANCE instance = GetModuleHandle(NULL); +#endif + // Load and pin user32.dll to avoid having to load it once tests start while + // on the main thread loop where blocking calls are disallowed. + base::win::PinUser32(); + sandbox::SandboxInterfaceInfo sandbox_info = {nullptr}; + content::InitializeSandboxInfo(&sandbox_info); + content::ShellMainDelegate delegate; + + content::ContentMainParams params(&delegate); + params.instance = instance; + params.sandbox_info = &sandbox_info; + return content::ContentMain(std::move(params)); +} + +#else + +int main(int argc, const char** argv) { + content::ShellMainDelegate delegate; + content::ContentMainParams params(&delegate); + params.argc = argc; + params.argv = argv; + return content::ContentMain(std::move(params)); +} + +#endif // BUILDFLAG(IS_WIN) diff --git a/chromium/content/shell/app/shell_main_delegate.cc b/chromium/content/shell/app/shell_main_delegate.cc new file mode 100644 index 00000000000..86e85bdc4ea --- /dev/null +++ b/chromium/content/shell/app/shell_main_delegate.cc @@ -0,0 +1,381 @@ +// Copyright (c) 2012 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 "content/shell/app/shell_main_delegate.h" + +#include <iostream> +#include <tuple> +#include <utility> + +#include "base/base_paths.h" +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/cpu.h" +#include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/path_service.h" +#include "base/trace_event/trace_log.h" +#include "build/build_config.h" +#include "components/crash/core/common/crash_key.h" +#include "content/common/content_constants_internal.h" +#include "content/public/browser/browser_main_runner.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/main_function_params.h" +#include "content/public/common/url_constants.h" +#include "content/shell/app/shell_crash_reporter_client.h" +#include "content/shell/browser/shell_content_browser_client.h" +#include "content/shell/browser/shell_paths.h" +#include "content/shell/common/shell_content_client.h" +#include "content/shell/common/shell_switches.h" +#include "content/shell/gpu/shell_content_gpu_client.h" +#include "content/shell/renderer/shell_content_renderer_client.h" +#include "content/shell/utility/shell_content_utility_client.h" +#include "ipc/ipc_buildflags.h" +#include "net/cookies/cookie_monster.h" +#include "ui/base/resource/resource_bundle.h" + +#if BUILDFLAG(IPC_MESSAGE_LOG_ENABLED) +#define IPC_MESSAGE_MACROS_LOG_ENABLED +#include "content/public/common/content_ipc_logging.h" +#define IPC_LOG_TABLE_ADD_ENTRY(msg_id, logger) \ + content::RegisterIPCLogger(msg_id, logger) +#endif + +#if !BUILDFLAG(IS_ANDROID) +#include "content/web_test/browser/web_test_browser_main_runner.h" // nogncheck +#include "content/web_test/browser/web_test_content_browser_client.h" // nogncheck +#include "content/web_test/renderer/web_test_content_renderer_client.h" // nogncheck +#endif + +#if BUILDFLAG(IS_ANDROID) +#include "base/android/apk_assets.h" +#include "base/posix/global_descriptors.h" +#include "content/public/browser/android/compositor.h" +#include "content/shell/android/shell_descriptors.h" +#endif + +#if !BUILDFLAG(IS_FUCHSIA) +#include "components/crash/core/app/crashpad.h" // nogncheck +#endif + +#if BUILDFLAG(IS_MAC) +#include "content/shell/app/paths_mac.h" +#include "content/shell/app/shell_main_delegate_mac.h" +#endif // BUILDFLAG(IS_MAC) + +#if BUILDFLAG(IS_WIN) +#include <windows.h> + +#include <initguid.h> +#include "base/logging_win.h" +#include "content/shell/common/v8_crashpad_support_win.h" +#endif + +#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID) +#include "v8/include/v8-wasm-trap-handler-posix.h" +#endif + +namespace { + +#if !BUILDFLAG(IS_FUCHSIA) +base::LazyInstance<content::ShellCrashReporterClient>::Leaky + g_shell_crash_client = LAZY_INSTANCE_INITIALIZER; +#endif + +#if BUILDFLAG(IS_WIN) +// If "Content Shell" doesn't show up in your list of trace providers in +// Sawbuck, add these registry entries to your machine (NOTE the optional +// Wow6432Node key for x64 machines): +// 1. Find: HKLM\SOFTWARE\[Wow6432Node\]Google\Sawbuck\Providers +// 2. Add a subkey with the name "{6A3E50A4-7E15-4099-8413-EC94D8C2A4B6}" +// 3. Add these values: +// "default_flags"=dword:00000001 +// "default_level"=dword:00000004 +// @="Content Shell" + +// {6A3E50A4-7E15-4099-8413-EC94D8C2A4B6} +const GUID kContentShellProviderName = { + 0x6a3e50a4, 0x7e15, 0x4099, + { 0x84, 0x13, 0xec, 0x94, 0xd8, 0xc2, 0xa4, 0xb6 } }; +#endif + +void InitLogging(const base::CommandLine& command_line) { + base::FilePath log_filename = + command_line.GetSwitchValuePath(switches::kLogFile); + if (log_filename.empty()) { +#if BUILDFLAG(IS_FUCHSIA) + base::PathService::Get(base::DIR_TEMP, &log_filename); +#else + base::PathService::Get(base::DIR_EXE, &log_filename); +#endif + log_filename = log_filename.AppendASCII("content_shell.log"); + } + + logging::LoggingSettings settings; + settings.logging_dest = logging::LOG_TO_ALL; + settings.log_file_path = log_filename.value().c_str(); + settings.delete_old = logging::DELETE_OLD_LOG_FILE; + logging::InitLogging(settings); + logging::SetLogItems(true /* Process ID */, true /* Thread ID */, + true /* Timestamp */, false /* Tick count */); +} + +} // namespace + +namespace content { + +ShellMainDelegate::ShellMainDelegate(bool is_content_browsertests) + : is_content_browsertests_(is_content_browsertests) {} + +ShellMainDelegate::~ShellMainDelegate() { +} + +bool ShellMainDelegate::BasicStartupComplete(int* exit_code) { + int dummy; + if (!exit_code) + exit_code = &dummy; + + base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess(); + if (command_line.HasSwitch("run-layout-test")) { + std::cerr << std::string(79, '*') << "\n" + << "* The flag --run-layout-test is obsolete. Please use --" + << switches::kRunWebTests << " instead. *\n" + << std::string(79, '*') << "\n"; + command_line.AppendSwitch(switches::kRunWebTests); + } + +#if BUILDFLAG(IS_ANDROID) + Compositor::Initialize(); +#endif + +#if BUILDFLAG(IS_WIN) + // Enable trace control and transport through event tracing for Windows. + logging::LogEventProvider::Initialize(kContentShellProviderName); + + v8_crashpad_support::SetUp(); +#endif + +#if BUILDFLAG(IS_MAC) + // Needs to happen before InitializeResourceBundle(). + OverrideFrameworkBundlePath(); + OverrideOuterBundlePath(); + OverrideChildProcessPath(); + OverrideSourceRootPath(); + EnsureCorrectResolutionSettings(); + OverrideBundleID(); +#endif // BUILDFLAG(IS_MAC) + + InitLogging(command_line); + +#if !BUILDFLAG(IS_ANDROID) + if (switches::IsRunWebTestsSwitchPresent()) { + const bool browser_process = + command_line.GetSwitchValueASCII(switches::kProcessType).empty(); + if (browser_process) { + web_test_runner_ = std::make_unique<WebTestBrowserMainRunner>(); + web_test_runner_->Initialize(); + } + } +#endif + + RegisterShellPathProvider(); + + return false; +} + +bool ShellMainDelegate::ShouldCreateFeatureList() { + return false; +} + +void ShellMainDelegate::PreSandboxStartup() { +#if defined(ARCH_CPU_ARM_FAMILY) && \ + (BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) + // Create an instance of the CPU class to parse /proc/cpuinfo and cache + // cpu_brand info. + base::CPU cpu_info; +#endif + +// Disable platform crash handling and initialize the crash reporter, if +// requested. +// TODO(crbug.com/1226159): Implement crash reporter integration for Fuchsia. +#if !BUILDFLAG(IS_FUCHSIA) + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableCrashReporter)) { + std::string process_type = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kProcessType); + crash_reporter::SetCrashReporterClient(g_shell_crash_client.Pointer()); + // Reporting for sub-processes will be initialized in ZygoteForked. + if (process_type != switches::kZygoteProcess) { + crash_reporter::InitializeCrashpad(process_type.empty(), process_type); +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + crash_reporter::SetFirstChanceExceptionHandler( + v8::TryHandleWebAssemblyTrapPosix); +#endif + } + } +#endif // !BUILDFLAG(IS_FUCHSIA) + + crash_reporter::InitializeCrashKeys(); + + InitializeResourceBundle(); +} + +absl::variant<int, MainFunctionParams> ShellMainDelegate::RunProcess( + const std::string& process_type, + MainFunctionParams main_function_params) { + // For non-browser process, return and have the caller run the main loop. + if (!process_type.empty()) + return std::move(main_function_params); + + base::trace_event::TraceLog::GetInstance()->set_process_name("Browser"); + base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex( + kTraceEventBrowserProcessSortIndex); + +#if !BUILDFLAG(IS_ANDROID) + if (switches::IsRunWebTestsSwitchPresent()) { + // Web tests implement their own BrowserMain() replacement. + web_test_runner_->RunBrowserMain(std::move(main_function_params)); + web_test_runner_.reset(); + // Returning 0 to indicate that we have replaced BrowserMain() and the + // caller should not call BrowserMain() itself. Web tests do not ever + // return an error. + return 0; + } + + // On non-Android, we can return the |main_function_params| back and have the + // caller run BrowserMain() normally. + return std::move(main_function_params); +#else + // On Android, we defer to the system message loop when the stack unwinds. + // So here we only create (and leak) a BrowserMainRunner. The shutdown + // of BrowserMainRunner doesn't happen in Chrome Android and doesn't work + // properly on Android at all. + std::unique_ptr<BrowserMainRunner> main_runner = BrowserMainRunner::Create(); + // In browser tests, the |main_function_params| contains a |ui_task| which + // will execute the testing. The task will be executed synchronously inside + // Initialize() so we don't depend on the BrowserMainRunner being Run(). + int initialize_exit_code = + main_runner->Initialize(std::move(main_function_params)); + DCHECK_LT(initialize_exit_code, 0) + << "BrowserMainRunner::Initialize failed in ShellMainDelegate"; + std::ignore = main_runner.release(); + // Return 0 as BrowserMain() should not be called after this, bounce up to + // the system message loop for ContentShell, and we're already done thanks + // to the |ui_task| for browser tests. + return 0; +#endif +} + +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +void ShellMainDelegate::ZygoteForked() { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableCrashReporter)) { + std::string process_type = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kProcessType); + crash_reporter::InitializeCrashpad(false, process_type); + crash_reporter::SetFirstChanceExceptionHandler( + v8::TryHandleWebAssemblyTrapPosix); + } +} +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + +void ShellMainDelegate::InitializeResourceBundle() { +#if BUILDFLAG(IS_ANDROID) + // On Android, the renderer runs with a different UID and can never access + // the file system. Use the file descriptor passed in at launch time. + auto* global_descriptors = base::GlobalDescriptors::GetInstance(); + int pak_fd = global_descriptors->MaybeGet(kShellPakDescriptor); + base::MemoryMappedFile::Region pak_region; + if (pak_fd >= 0) { + pak_region = global_descriptors->GetRegion(kShellPakDescriptor); + } else { + pak_fd = + base::android::OpenApkAsset("assets/content_shell.pak", &pak_region); + // Loaded from disk for browsertests. + if (pak_fd < 0) { + base::FilePath pak_file; + bool r = base::PathService::Get(base::DIR_ANDROID_APP_DATA, &pak_file); + DCHECK(r); + pak_file = pak_file.Append(FILE_PATH_LITERAL("paks")); + pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak")); + int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; + pak_fd = base::File(pak_file, flags).TakePlatformFile(); + pak_region = base::MemoryMappedFile::Region::kWholeFile; + } + global_descriptors->Set(kShellPakDescriptor, pak_fd, pak_region); + } + DCHECK_GE(pak_fd, 0); + // TODO(crbug.com/330930): A better way to prevent fdsan error from a double + // close is to refactor GlobalDescriptors.{Get,MaybeGet} to return + // "const base::File&" rather than fd itself. + base::File android_pak_file(pak_fd); + ui::ResourceBundle::InitSharedInstanceWithPakFileRegion( + android_pak_file.Duplicate(), pak_region); + ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion( + std::move(android_pak_file), pak_region, ui::k100Percent); +#elif BUILDFLAG(IS_MAC) + ui::ResourceBundle::InitSharedInstanceWithPakPath(GetResourcesPakFilePath()); +#else + base::FilePath pak_file; + bool r = base::PathService::Get(base::DIR_ASSETS, &pak_file); + DCHECK(r); + pak_file = pak_file.Append(FILE_PATH_LITERAL("content_shell.pak")); + ui::ResourceBundle::InitSharedInstanceWithPakPath(pak_file); +#endif +} + +void ShellMainDelegate::PreBrowserMain() { +#if BUILDFLAG(IS_MAC) + RegisterShellCrApp(); +#endif +} + +void ShellMainDelegate::PostEarlyInitialization(bool is_running_tests) { + // Apply field trial testing configuration. + browser_client_->CreateFeatureListAndFieldTrials(); +} + +ContentClient* ShellMainDelegate::CreateContentClient() { + content_client_ = std::make_unique<ShellContentClient>(); + return content_client_.get(); +} + +ContentBrowserClient* ShellMainDelegate::CreateContentBrowserClient() { +#if !BUILDFLAG(IS_ANDROID) + if (switches::IsRunWebTestsSwitchPresent()) { + browser_client_ = std::make_unique<WebTestContentBrowserClient>(); + return browser_client_.get(); + } +#endif + browser_client_ = std::make_unique<ShellContentBrowserClient>(); + return browser_client_.get(); +} + +ContentGpuClient* ShellMainDelegate::CreateContentGpuClient() { + gpu_client_ = std::make_unique<ShellContentGpuClient>(); + return gpu_client_.get(); +} + +ContentRendererClient* ShellMainDelegate::CreateContentRendererClient() { +#if !BUILDFLAG(IS_ANDROID) + if (switches::IsRunWebTestsSwitchPresent()) { + renderer_client_ = std::make_unique<WebTestContentRendererClient>(); + return renderer_client_.get(); + } +#endif + renderer_client_ = std::make_unique<ShellContentRendererClient>(); + return renderer_client_.get(); +} + +ContentUtilityClient* ShellMainDelegate::CreateContentUtilityClient() { + utility_client_ = + std::make_unique<ShellContentUtilityClient>(is_content_browsertests_); + return utility_client_.get(); +} + +} // namespace content diff --git a/chromium/content/shell/app/shell_main_delegate.h b/chromium/content/shell/app/shell_main_delegate.h new file mode 100644 index 00000000000..f19ee28d6c8 --- /dev/null +++ b/chromium/content/shell/app/shell_main_delegate.h @@ -0,0 +1,77 @@ +// Copyright (c) 2012 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. + +#ifndef CONTENT_SHELL_APP_SHELL_MAIN_DELEGATE_H_ +#define CONTENT_SHELL_APP_SHELL_MAIN_DELEGATE_H_ + +#include <memory> + +#include "build/build_config.h" +#include "content/public/app/content_main_delegate.h" + +namespace content { +class ShellContentClient; +class ShellContentBrowserClient; +class ShellContentGpuClient; +class ShellContentRendererClient; +class ShellContentUtilityClient; + +#if !BUILDFLAG(IS_ANDROID) +class WebTestBrowserMainRunner; +#endif + +class ShellMainDelegate : public ContentMainDelegate { + public: + explicit ShellMainDelegate(bool is_content_browsertests = false); + + ShellMainDelegate(const ShellMainDelegate&) = delete; + ShellMainDelegate& operator=(const ShellMainDelegate&) = delete; + + ~ShellMainDelegate() override; + + // ContentMainDelegate implementation: + bool BasicStartupComplete(int* exit_code) override; + bool ShouldCreateFeatureList() override; + void PreSandboxStartup() override; + absl::variant<int, MainFunctionParams> RunProcess( + const std::string& process_type, + MainFunctionParams main_function_params) override; +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + void ZygoteForked() override; +#endif + void PreBrowserMain() override; + void PostEarlyInitialization(bool is_running_tests) override; + ContentClient* CreateContentClient() override; + ContentBrowserClient* CreateContentBrowserClient() override; + ContentGpuClient* CreateContentGpuClient() override; + ContentRendererClient* CreateContentRendererClient() override; + ContentUtilityClient* CreateContentUtilityClient() override; + + static void InitializeResourceBundle(); + + protected: + // Only present when running content_browsertests, which run inside Content + // Shell. + // + // content_browsertests should not set the kRunWebTests command line flag, so + // |is_content_browsertests_| and |web_test_runner_| are mututally exclusive. + bool is_content_browsertests_; +#if !BUILDFLAG(IS_ANDROID) + // Only present when running web tests, which run inside Content Shell. + // + // Web tests are not browser tests, so |is_content_browsertests_| and + // |web_test_runner_| are mututally exclusive. + std::unique_ptr<WebTestBrowserMainRunner> web_test_runner_; +#endif + + std::unique_ptr<ShellContentBrowserClient> browser_client_; + std::unique_ptr<ShellContentGpuClient> gpu_client_; + std::unique_ptr<ShellContentRendererClient> renderer_client_; + std::unique_ptr<ShellContentUtilityClient> utility_client_; + std::unique_ptr<ShellContentClient> content_client_; +}; + +} // namespace content + +#endif // CONTENT_SHELL_APP_SHELL_MAIN_DELEGATE_H_ diff --git a/chromium/content/shell/app/shell_main_delegate_mac.h b/chromium/content/shell/app/shell_main_delegate_mac.h new file mode 100644 index 00000000000..fe9696855c1 --- /dev/null +++ b/chromium/content/shell/app/shell_main_delegate_mac.h @@ -0,0 +1,22 @@ +// Copyright 2013 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. + +#ifndef CONTENT_SHELL_APP_SHELL_MAIN_DELEGATE_MAC_H_ +#define CONTENT_SHELL_APP_SHELL_MAIN_DELEGATE_MAC_H_ + +namespace content { + +// Set NSHighResolutionCapable to false when running layout tests, so we match +// the expected pixel results on retina capable displays. +void EnsureCorrectResolutionSettings(); + +// Sets up base::mac::BaseBundleID. +void OverrideBundleID(); + +// Initializes NSApplication. +void RegisterShellCrApp(); + +} // namespace content + +#endif // CONTENT_SHELL_APP_SHELL_MAIN_DELEGATE_MAC_H_ diff --git a/chromium/content/shell/app/shell_main_delegate_mac.mm b/chromium/content/shell/app/shell_main_delegate_mac.mm new file mode 100644 index 00000000000..c1c3917db0b --- /dev/null +++ b/chromium/content/shell/app/shell_main_delegate_mac.mm @@ -0,0 +1,72 @@ +// Copyright 2013 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 "content/shell/app/shell_main_delegate_mac.h" + +#include <unistd.h> + +#include "base/check.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#include "base/mac/scoped_nsobject.h" +#include "base/strings/sys_string_conversions.h" +#include "content/public/common/content_switches.h" +#include "content/shell/app/paths_mac.h" +#include "content/shell/browser/shell_application_mac.h" +#include "content/shell/common/shell_switches.h" + +namespace content { + +void EnsureCorrectResolutionSettings() { + // Exit early if this isn't a browser process. + if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kProcessType)) + return; + + NSString* const kHighResolutionCapable = @"NSHighResolutionCapable"; + base::FilePath info_plist = GetInfoPlistPath(); + base::scoped_nsobject<NSMutableDictionary> info_dict( + [[NSMutableDictionary alloc] + initWithContentsOfFile:base::mac::FilePathToNSString(info_plist)]); + + bool running_web_tests = switches::IsRunWebTestsSwitchPresent(); + bool not_high_resolution_capable = + [info_dict objectForKey:kHighResolutionCapable] && + [[info_dict objectForKey:kHighResolutionCapable] isEqualToNumber:@(NO)]; + if (running_web_tests == not_high_resolution_capable) + return; + + // We need to update our Info.plist before we can continue. + [info_dict setObject:@(!running_web_tests) forKey:kHighResolutionCapable]; + CHECK([info_dict writeToFile:base::mac::FilePathToNSString(info_plist) + atomically:YES]); + + const base::CommandLine::StringVector& original_argv = + base::CommandLine::ForCurrentProcess()->argv(); + char** argv = new char*[original_argv.size() + 1]; + for (unsigned i = 0; i < original_argv.size(); ++i) + argv[i] = const_cast<char*>(original_argv.at(i).c_str()); + argv[original_argv.size()] = NULL; + + CHECK(execvp(argv[0], argv)); +} + +void OverrideBundleID() { + NSBundle* bundle = base::mac::OuterBundle(); + base::mac::SetBaseBundleID( + base::SysNSStringToUTF8([bundle bundleIdentifier]).c_str()); +} + +void RegisterShellCrApp() { + // Force the NSApplication subclass to be used. + [ShellCrApplication sharedApplication]; + + // If there was an invocation to NSApp prior to this method, then the NSApp + // will not be a ShellCrApplication, but will instead be an NSApplication. + // This is undesirable and we must enforce that this doesn't happen. + CHECK([NSApp isKindOfClass:[ShellCrApplication class]]); +} + +} // namespace content 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); +} |