From 78e49e2efb49f909a389e66260574b1ed3101633 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Fri, 3 Jun 2016 12:49:39 -0700 Subject: [PATCH] Bug 1114647 - Use firefox for child processes instead of plugin-container. r=ted Disabled on Mac (content processes need to use plugin-container.app for UI reasons) and on Linux unless --disable-sandboxing (build issues). Based on work by George Wright . --HG-- extra : amend_source : 43986e25743de21e3ddfb7893e3ed550fe6eef76 --- browser/app/nsBrowserApp.cpp | 65 +++++++++++++++++++++++----- ipc/app/moz.build | 5 +++ ipc/contentproc/plugin-container.cpp | 12 +++-- ipc/glue/GeckoChildProcessHost.cpp | 38 ++++++++++++++-- ipc/glue/GeckoChildProcessHost.h | 6 ++- toolkit/xre/nsAppRunner.cpp | 6 +++ xpcom/build/nsXULAppAPI.h | 3 ++ 7 files changed, 113 insertions(+), 22 deletions(-) diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp index 0989d264e826..f8c9ad610510 100644 --- a/browser/app/nsBrowserApp.cpp +++ b/browser/app/nsBrowserApp.cpp @@ -30,14 +30,12 @@ #include "nsStringGlue.h" #ifdef XP_WIN -// we want a wmain entry point #ifdef MOZ_ASAN // ASAN requires firefox.exe to be built with -MD, and it's OK if we don't // support Windows XP SP2 in ASAN builds. #define XRE_DONT_SUPPORT_XPSP2 #endif #define XRE_WANT_ENVIRON -#include "nsWindowsWMain.cpp" #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf #endif @@ -53,6 +51,12 @@ #include "mozilla/Telemetry.h" #include "mozilla/WindowsDllBlocklist.h" +#if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) \ + && !(defined(XP_LINUX) && defined(MOZ_SANDBOX)) +#define MOZ_BROWSER_CAN_BE_CONTENTPROC +#include "../../ipc/contentproc/plugin-container.cpp" +#endif + using namespace mozilla; #ifdef XP_MACOSX @@ -128,6 +132,10 @@ XRE_StartupTimelineRecordType XRE_StartupTimelineRecord; XRE_mainType XRE_main; XRE_StopLateWriteChecksType XRE_StopLateWriteChecks; XRE_XPCShellMainType XRE_XPCShellMain; +XRE_GetProcessTypeType XRE_GetProcessType; +XRE_SetProcessTypeType XRE_SetProcessType; +XRE_InitChildProcessType XRE_InitChildProcess; +XRE_EnableSameExecutableForContentProcType XRE_EnableSameExecutableForContentProc; static const nsDynamicFunctionLoad kXULFuncs[] = { { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath }, @@ -138,6 +146,10 @@ static const nsDynamicFunctionLoad kXULFuncs[] = { { "XRE_main", (NSFuncPtr*) &XRE_main }, { "XRE_StopLateWriteChecks", (NSFuncPtr*) &XRE_StopLateWriteChecks }, { "XRE_XPCShellMain", (NSFuncPtr*) &XRE_XPCShellMain }, + { "XRE_GetProcessType", (NSFuncPtr*) &XRE_GetProcessType }, + { "XRE_SetProcessType", (NSFuncPtr*) &XRE_SetProcessType }, + { "XRE_InitChildProcess", (NSFuncPtr*) &XRE_InitChildProcess }, + { "XRE_EnableSameExecutableForContentProc", (NSFuncPtr*) &XRE_EnableSameExecutableForContentProc }, { nullptr, nullptr } }; @@ -296,25 +308,54 @@ sizeof(XPCOM_DLL) - 1)) // This will set this thread as the main thread. NS_LogInit(); - // chop XPCOM_DLL off exePath - *lastSlash = '\0'; + if (xreDirectory) { + // chop XPCOM_DLL off exePath + *lastSlash = '\0'; #ifdef XP_MACOSX - lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); - strcpy(lastSlash + 1, kOSXResourcesFolder); + lastSlash = strrchr(exePath, XPCOM_FILE_PATH_SEPARATOR[0]); + strcpy(lastSlash + 1, kOSXResourcesFolder); #endif #ifdef XP_WIN - rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false, - xreDirectory); + rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(exePath), false, + xreDirectory); #else - rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false, - xreDirectory); + rv = NS_NewNativeLocalFile(nsDependentCString(exePath), false, + xreDirectory); #endif + } return rv; } int main(int argc, char* argv[], char* envp[]) { +#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC + // We are launching as a content process, delegate to the appropriate + // main + if (argc > 1 && IsArg(argv[1], "contentproc")) { +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + // We need to initialize the sandbox TargetServices before InitXPCOMGlue + // because we might need the sandbox broker to give access to some files. + if (!sandboxing::GetInitializedTargetServices()) { + Output("Failed to initialize the sandbox target services."); + return 255; + } +#endif + + nsresult rv = InitXPCOMGlue(argv[0], nullptr); + if (NS_FAILED(rv)) { + return 255; + } + + int result = content_process_main(argc, argv); + + // InitXPCOMGlue calls NS_LogInit, so we need to balance it here. + NS_LogTerm(); + + return result; + } +#endif + mozilla::TimeStamp start = mozilla::TimeStamp::Now(); #ifdef XP_MACOSX @@ -379,6 +420,10 @@ int main(int argc, char* argv[], char* envp[]) #endif } +#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC + XRE_EnableSameExecutableForContentProc(); +#endif + int result = do_main(argc, argv, envp, xreDirectory); NS_LogTerm(); diff --git a/ipc/app/moz.build b/ipc/app/moz.build index 55fdf6fc07c0..6c89083e5b8c 100644 --- a/ipc/app/moz.build +++ b/ipc/app/moz.build @@ -92,3 +92,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'binder', 'utils', ] + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wshadow'] + +DEFINES['MOZ_PLUGIN_CONTAINER'] = 1; diff --git a/ipc/contentproc/plugin-container.cpp b/ipc/contentproc/plugin-container.cpp index 6119996baff0..555403238f26 100644 --- a/ipc/contentproc/plugin-container.cpp +++ b/ipc/contentproc/plugin-container.cpp @@ -8,11 +8,6 @@ #include "nsXULAppAPI.h" #include "nsAutoPtr.h" -// FIXME/cjones testing -#if !defined(OS_WIN) -#include -#endif - #ifdef XP_WIN #include // we want a wmain entry point @@ -20,6 +15,9 @@ #define XRE_DONT_PROTECT_DLL_LOAD #include "nsWindowsWMain.cpp" #include "nsSetDllDirectory.h" +#else +// FIXME/cjones testing +#include #endif #include "GMPLoader.h" @@ -217,10 +215,10 @@ content_process_main(int argc, char* argv[]) // the details. if (XRE_GetProcessType() != GeckoProcessType_Plugin) { mozilla::SanitizeEnvironmentVariables(); - SetDllDirectory(L""); + SetDllDirectoryW(L""); } #endif -#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK) +#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK) && defined(MOZ_PLUGIN_CONTAINER) // On desktop, the GMPLoader lives in plugin-container, so that its // code can be covered by an EME/GMP vendor's voucher. nsAutoPtr starter(MakeSandboxStarter()); diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 5edb246d023f..a730d3f56061 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -139,8 +139,24 @@ GeckoChildProcessHost::~GeckoChildProcessHost() //static void -GeckoChildProcessHost::GetPathToBinary(FilePath& exePath) +GeckoChildProcessHost::GetPathToBinary(FilePath& exePath, GeckoProcessType processType) { + if (sRunSelfAsContentProc && + processType == GeckoProcessType_Content) { +#if defined(OS_WIN) + wchar_t exePathBuf[MAXPATHLEN]; + if (!::GetModuleFileNameW(nullptr, exePathBuf, MAXPATHLEN)) { + MOZ_CRASH("GetModuleFileNameW failed (FIXME)"); + } + exePath = FilePath::FromWStringHack(exePathBuf); +#elif defined(OS_POSIX) + exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]); +#else +# error Sorry; target OS not supported yet. +#endif + return; + } + if (ShouldHaveDirectoryService()) { MOZ_ASSERT(gGREBinPath); #ifdef OS_WIN @@ -149,6 +165,7 @@ GeckoChildProcessHost::GetPathToBinary(FilePath& exePath) nsCOMPtr childProcPath; NS_NewLocalFile(nsDependentString(gGREBinPath), false, getter_AddRefs(childProcPath)); + // We need to use an App Bundle on OS X so that we can hide // the dock icon. See Bug 557225. childProcPath->AppendNative(NS_LITERAL_CSTRING("plugin-container.app")); @@ -259,7 +276,7 @@ uint32_t GeckoChildProcessHost::GetSupportedArchitecturesForProcessType(GeckoPro static uint32_t pluginContainerArchs = 0; if (pluginContainerArchs == 0) { FilePath exePath; - GetPathToBinary(exePath); + GetPathToBinary(exePath, type); nsresult rv = GetArchitecturesForBinary(exePath.value().c_str(), &pluginContainerArchs); NS_ASSERTION(NS_SUCCEEDED(rv) && pluginContainerArchs != 0, "Getting architecture of plugin container failed!"); if (NS_FAILED(rv) || pluginContainerArchs == 0) { @@ -785,7 +802,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt #endif // OS_LINUX || OS_MACOSX FilePath exePath; - GetPathToBinary(exePath); + GetPathToBinary(exePath, mProcessType); #ifdef MOZ_WIDGET_ANDROID // The java wrapper unpacks this for us but can't make it executable @@ -828,6 +845,11 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt childArgv.push_back(exePath.value()); + if (sRunSelfAsContentProc && + mProcessType == GeckoProcessType_Content) { + childArgv.push_back("-contentproc"); + } + childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end()); if (Omnijar::IsInitialized()) { @@ -964,9 +986,15 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector& aExt #elif defined(OS_WIN) FilePath exePath; - GetPathToBinary(exePath); + GetPathToBinary(exePath, mProcessType); CommandLine cmdLine(exePath.ToWStringHack()); + + if (sRunSelfAsContentProc && + mProcessType == GeckoProcessType_Content) { + cmdLine.AppendLooseValue(UTF8ToWide("-contentproc")); + } + cmdLine.AppendSwitchWithValue(switches::kProcessChannelID, channel_id()); for (std::vector::iterator it = aExtraOpts.begin(); @@ -1211,6 +1239,8 @@ GeckoChildProcessHost::OnWaitableEventSignaled(base::WaitableEvent *event) ChildProcessHost::OnWaitableEventSignaled(event); } +bool GeckoChildProcessHost::sRunSelfAsContentProc(false); + #ifdef MOZ_NUWA_PROCESS using mozilla::ipc::GeckoExistingProcessHost; diff --git a/ipc/glue/GeckoChildProcessHost.h b/ipc/glue/GeckoChildProcessHost.h index 372f4ddff594..146c9f9b1ac5 100644 --- a/ipc/glue/GeckoChildProcessHost.h +++ b/ipc/glue/GeckoChildProcessHost.h @@ -136,6 +136,8 @@ public: // for deletion when all actors have cleared their associations. void DissociateActor(); + static void EnableSameExecutableForContentProc() { sRunSelfAsContentProc = true; } + protected: GeckoProcessType mProcessType; ChildPrivileges mPrivileges; @@ -200,7 +202,7 @@ private: bool RunPerformAsyncLaunch(StringVector aExtraOpts=StringVector(), base::ProcessArchitecture aArch=base::GetCurrentProcessArchitecture()); - static void GetPathToBinary(FilePath& exePath); + static void GetPathToBinary(FilePath& exePath, GeckoProcessType processType); // The buffer is passed to preserve its lifetime until we are done // with launching the sub-process. @@ -227,6 +229,8 @@ private: nsCString mRestoreOrigMozLogName; static uint32_t sNextUniqueID; + + static bool sRunSelfAsContentProc; }; #ifdef MOZ_NUWA_PROCESS diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 9e6492626d80..de85402e5cbf 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -11,6 +11,7 @@ #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentChild.h" +#include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/ArrayUtils.h" #include "mozilla/Attributes.h" @@ -4962,3 +4963,8 @@ OverrideDefaultLocaleIfNeeded() { setlocale(LC_ALL, "C.UTF-8") || setlocale(LC_ALL, "C"); } } + +void +XRE_EnableSameExecutableForContentProc() { + mozilla::ipc::GeckoChildProcessHost::EnableSameExecutableForContentProc(); +} diff --git a/xpcom/build/nsXULAppAPI.h b/xpcom/build/nsXULAppAPI.h index c7892207d7ed..ed27622b271a 100644 --- a/xpcom/build/nsXULAppAPI.h +++ b/xpcom/build/nsXULAppAPI.h @@ -507,6 +507,9 @@ XRE_API(void, const nsXREAppData* aAppData)); #endif // MOZ_B2G_LOADER +XRE_API(void, + XRE_EnableSameExecutableForContentProc, ()) + XRE_API(int, XRE_XPCShellMain, (int argc, char** argv, char** envp, const XREShellData* aShellData))