Files
palemoon27/toolkit/xre/nsEmbedFunctions.cpp
roytam1 b564bd67d3 import changes from `dev' branch of rmottola/Arctic-Fox:
- Use CompositorWidgetProxy for dispatching vsync to the compositor. (bug 1269037 part 1, r=mchang) (c8b7a4240c)
- Remove unused null widget checks. (bug 1269037 part 2, r=mchang) (4f4cc9952b)
- Bug 1269422: Wrap Gonk widget in |CompositorWidgetProxyWrapper|. r=dvander (4513035cbf)
- Remove nsBaseWidget::NewCompositorBridgeParent. (bug 1272472 part 1, r=kats) (ca813c1f2b)
- Use IPDL to schedule composites on GTK. (bug 1272472 part 2, r=nical) (7402cf834e)
- Use IPC to schedule composites on Windows. (bug 1272472 part 3, r=jimm) (e5d7281dd7)
- Don't use nsIWidget to check APZ in LayerManagerComposite. (bug 1269653 part 1, r=kats) (79a1644111)
- Restrict SetDispAcquireFence's nsIWidget access to Gonk. (bug 1269653 part 2, r=kats) (72110b7bc7)
- Bug 1264764 - Move PTexture under PCompositorBridge r=nical,dvander (17e6ec7fc1)
- Move CompositorThreadHolder into its own file. (bug 1273017 part 1, r=mattwoodrow) (464ede8be1)
- Move CompositorBridgeParent::CompositorLoop to CompositorThreadHolder. (bug 1273017 part 2, r=mattwoodrow) (85708f3cde)
- Bug 1268313: Part 1 - Be explicit about which NewRunnableMethod callers want to be able to cancel. r=froydnj (faa07aa139)
- Bug 1268313: Part 2 - Replace some NewRunnableMethods with NS_NewNonOwningRunnableMethod. r=froydnj (010c43d000)
- Bug 1268313: Part 3 - Replace some NewCancelableRunnableMethod with NS_NewNonOwningCancelableRunnableMethod. r=froydnj (55018ef234)
- Bug 1268313: Part 4 - Replace NewCancelableRunnableMethod with NS_NewCancelableRunnableMethod. r=froydnj (c22711b35d)
- Bug 1268313: Part 5 - Make NS_NewRunnableMethod able to call const functions. r=froydnj (b0f60963a3)
- Bug 1268313: Part 6 - Replace NewRunnableMethod with NS_NewRunnableMethod. r=froydnj (18d40def2c)
- Bug 1260950 - Set mInitialSizeFound to true when the initial size id found. r=jesup, r=pehrsons a=kwierso (5d6abe57e0)
- Bug 1237176 - Notify synth start if we get a finished event without a blocking-changed event. r=roc (c1aebe903a)
- Bug 911546, use a runnable so that popups don't rollup during a grab, r=karlt (a06bd44e6c)
- Bug 1237617 - Call nsWindow::ForcePresent during going active r=bas.schouten (066cad8f89)
- Bug 1268313: Part 7 - Move NS_NewRunnableMethod and friends to mozilla::NewRunnableMethod. r=froydnj (8b4bf34961)
- Bug 1266595: Followup to fix IPDL tests. r=billm (216f2dcff5)
- Bug 1268313: Fix up IPDL tests. r=billm (228348d642)
- Add WinCompositorWidgetProxy. (bug 1265975 part 1, r=jimm) (bfafe7a8e2)
- Implement WinCompositorWidgetProxy::GetClientSize. (bug 1265975 part 2, r=jimm) (a8710a3259)
- Move the WM_SETTEXT present lock to CompositorWidgetProxy. (bug 1265975 part 3, r=jimm) (297ce28c8a)
- Move transparency handling to WinCompositorWigetProxy. (bug 1265975 part 4, r=jimm) (46ba0c6d01)
- Remove Windows-specific compositor calls to nsIWidget. (bug 1265975 part 5, r=jimm) (3ef157c160)
- Remove plugin-related CompositorBridgeParent use of nsIWidget. (bug 1265975 part 6, r=jimm) (6d80cdd6fd)
- Hide top-level CompositorBridgeParents behind a new API. (bug 1272472 part 4, r=mattwoodrow,kats,gwagner) (228c0efdb7)
- Bug 1253424 - part 1 - add a already_AddRefed nsTransactionStack::Push overload; r=erahm (7059e20914)
- Bug 1253424 - part 2 - add nsTransactionStack::IsEmpty; r=erahm (7e9764a146)
- Bug 1254618 - modify nsTransactionStack to use nsDeque rather than std::deque; r=ehsan (5e47ea431e)
- Bug 1136857 - Make DOMStorageCache::mLoaded flag atomic to prevent potential races, r=nfroyd (39aaea1de3)
- Bug 1265408 - Add webidl for IIRFilterNode; r=smaug (040ce9aa43)
- Bug 1265408 - Implement IIRFilterNode; r=padenot (6bf569a412)
- Bug 1265408 - Import IIRFilter from blink; r=padenot (71b28c0ad2)
- Bug 1265408 - Use IIRFilter from blink; r=padenot (5d058d8568)
- Bug 1265408 - Add buffersAreZero to IIRFilter; r=karlt (45edba3e13)
- Bug 1265408 - Avoid subnormals in IIRFilter; r=karlt (0e1ae93f0b)
- Bug 1265408 - Add LogToDeveloperConsole to WebAudioUtils; r=padenot (88d5f0222a)
- Bug 1268984 - Store GMPStorage on GMPServiceParent so that it persists inside the same PB session. r=gerald (17d4d0abaf)
- Bug 1267905 - Replace uses of ScopedCERTCertList with UniqueCERTCertList. r=keeler (783bf11b2a)
- Bug 1270005 - Replace uses of ScopedPK11SlotInfo with UniquePK11SlotInfo in PSM. r=keeler (ea9a4011aa)
- Bug 1271501 - Remove unnecessary uses of reinterpret_cast in PSM. r=keeler (6be40f0a85)
- Bug 1271501 - Downgrade unnecessarily strong reinterpret_casts in PSM. r=keeler (95245f00ce)
- Bug 1082346 - 01. Convert PKCS12 password endian using copyAndSwapToBigEndian. r=keeler (9cc58fc550)
- Bug 1082346 - 02. Test case. r=keeler r=Cykesiopka (7fb0e8abc4)
- Bug 160122 - Stop using PR_smprintf in PSM. r=keeler (1e5b68819c)
- Bug 1271501 - Use mozilla::BitwiseCast instead of reinterpret_cast in PSM. r=keeler (894966a2ef)
- Bug 1273855: TraceLogger - Include PID in the log names in order to support browser with e10s, r=bbouvier (8cf2233db3)
- Bug 1274189. Part 1 - rename some functions to be consistent with other MediaDataDecoder sub-classes. r=jya. (4511b3d3f7)
- Bug 1274189. Part 2 - remove use of FlushableTaskQueue::Flush(). r=jya. (77e745fdd1)
- Bug 1274189. Part 3 - remove use of FlushableTaskQueue. r=jya (aac61dcd02)
- Bug 1269963. Part 1 - Add a SyncRunnable::DispatchToThread() overload for AbstractThread. r=bobbyholley. (839752aff4)
- Bug 1269672 - part1 : revert sampling rate changing of the bug1235612. (9015782e13)
- Bug 1270698 - check if we need to enter buffering periodically to ensure we start buffering when running out of decoded audio/video data. r=cpearce. (16734549b7)
- Bug 1271581 - use newCurrentTime, instead of GetMediaTime() to decide the nextState; r=jwwang (9c5075eada)
- Bug 1224973 - Part 1: Remove MediaDecoderOwner->IsHidden(). r=cpearce,jwwang (4fde3ede5a)
- Bug 1224973 - Part 2: Set MediaDecoder visibility via NotifyOwnerActivityChanged. r=cpearce,jwwang (be917202eb)
- Bug 1224973 - Part 3: Plumb element visibility into MDSM. r=jya,jwwang (9ec83fa243)
- Bug 1224973 - Part 4: Pref media.suspend-bkgnd-video.enabled. r=cpearce,jwwang (43413a025f)
- Bug 1269408: P1. Retry InternalSeek if previous attempt failed once more data is available. r=gerald (05db58dc7c)
- crude fix (0097068989)
- Bug 1269408: P2. Update mochitest. r=gerald (464b4c0724)
- Bug 1269408: P3. Ensure a new seek request will cancel the previous internal seek. r=gerald (6ed4b8dc95)
- Bug 1269408: P4. Ensure the decoders are flushed prior performing an internal seek. r=gerald (074234067b)
- Bug 1269408: P5. Only drop the seek target if it's exactly the seek target. r=gerald (88701eb05a)
- Bug 1269408: P6. Add debugging information, useful when a mochitest timeout. r=gerald (ef0270ab0d)
- Bug 1269408: P7. Start skip to next keyframe logic when resume point is behind current time. r=gerald (bd40ebf3bc)
- Bug 1269408: P8. Add debugging log. r=gerald (e6dbd1f0a6)
- Bug 1269408: P9. Move handling logic of skip to next keyframe to its own function. r=gerald (3c8039e417)
- Bug 1269408: P10. Reject promise early if in error state. r=me (8af54c574e)
- Bug 1224973 - Part 5: Implement suspend decoding for background video. r=cpearce,jwwang,jya (22081521e3)
- Bug 1242874 - part1 : create suspened types. r=baku (d3ac9548e5)
- Bug 1242874 - part2 : window's suspend attribute. r=baku, r=ehsan (1fd9dc2647)
- remove allowscirpted (39ab523036)
- Bug 1242874 - part3 : implement different suspended methods. r=baku, r=jwwang (25d1f27a03)
- Bug 1242874 - part4 : wrap the volume/mute/suspend for notifyStartedPlaying. r=baku (b8ba3238c2)
- bug 1242874 - part5 : add test. r=baku, r=ehsan (f840139b5a)
- Bug 1235612 - Part 1: Implement notify media-playback. r=baku (b5ec29da20)
- Bug 1235612 - Part 2: Notify audible state in NotifyStartedPlaying. r=baku (dc38583a62)
- Bug 1235612 - Part 3: Implement the logic of audible state notification for agent owners. r=baku (f65b3952fa)
- Bug 1235612 - Part 4: Modify check audible method. r=jwwang (73457e39eb)
- Bug 1269672 - part2 : move audible data checking from MDSM to DecodedAudioDataSink. (d2c3b6874c)
- Bug 1269936 - Introduce and call a runtime-wide servo initialization hook. r=heycam (d4d505d4c2)
- Bug 1263778 - Rename a bunch of low-level [[Prototype]] access methods to make their interactions with statically-known and dynamically-computed [[Prototype]]s clearer. r=efaust (66bbe8e7db)
- Bug 888969 - Permit a cyclic [[Prototype]] chain to be created through a Location object. r=bz, r=efaust (3e3b9cbb16)
- re-apply Bug 1054906 - Implement ES6 Symbol.hasInstance 2/2; r=jandem (8d5c7573ff)
- Bug 1054906 - Implement ES6 Symbol.hasInstance 1/2; r=evilpie,bz (a836904e5d)
- fix misspatch (54a5f2d708)
- Bug 1270349 part 1. Add IDL parser support for [LegacyUnenumerableNamedProperties]. r=peterv (8c836bc74a)
- Bug 1270349 part 2. Add [LegacyUnenumerableNamedProperties] to the interfaces that specify it in DOM and HTML. r=peterv (25d3cc1377)
- Bug 1270349 part 3. Add a way to ask an interface descriptor for a proxy whether its named props should be enumerable. r=peterv (0a9f804867)
- Bug 1270349 part 4. Use LegacyUnenumerableNamedProperties instead of NameIsEnumerable() calls to determine whether named props on DOM proxies should be enumerable. r=peterv (82f5158963)
- Bug 1270349 part 5. Use LegacyUnenumerableNamedProperties instead of passing flags to GetSupportedNames to determine whether named props on DOM proxies should be reflected in ownPropertyKeys. r=peterv (3984176834)
- Bug 1270349 followup to address a review comment. r=peterv (b49f4c5335)
2024-10-03 21:54:00 +08:00

943 lines
27 KiB
C++

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/DebugOnly.h"
#if defined(MOZ_WIDGET_QT)
#include "nsQAppInstance.h"
#endif
#include "base/basictypes.h"
#include "nsXULAppAPI.h"
#include <stdlib.h>
#if defined(MOZ_WIDGET_GTK)
#include <glib.h>
#endif
#include "prenv.h"
#include "nsIAppShell.h"
#include "nsIAppStartupNotifier.h"
#include "nsIDirectoryService.h"
#include "nsIFile.h"
#include "nsIToolkitChromeRegistry.h"
#include "nsIToolkitProfile.h"
#ifdef XP_WIN
#include <process.h>
#include "mozilla/ipc/WindowsMessageLoop.h"
#endif
#include "nsAppDirectoryServiceDefs.h"
#include "nsAppRunner.h"
#include "nsAutoRef.h"
#include "nsDirectoryServiceDefs.h"
#include "nsExceptionHandler.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsJSUtils.h"
#include "nsWidgetsCID.h"
#include "nsXREDirProvider.h"
#include "mozilla/Omnijar.h"
#if defined(XP_MACOSX)
#include "nsVersionComparator.h"
#include "chrome/common/mach_ipc_mac.h"
#endif
#include "nsX11ErrorHandler.h"
#include "nsGDKErrorHandler.h"
#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/process_util.h"
#include "chrome/common/child_process.h"
#include "chrome/common/notification_service.h"
#include "mozilla/ipc/BrowserProcessSubThread.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
#include "mozilla/ipc/IOThreadChild.h"
#include "mozilla/ipc/ProcessChild.h"
#include "ScopedXREEmbed.h"
#include "mozilla/plugins/PluginProcessChild.h"
#include "mozilla/dom/ContentProcess.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/ipc/TestShellParent.h"
#include "mozilla/ipc/XPCShellEnvironment.h"
#include "mozilla/WindowsDllBlocklist.h"
#include "GMPProcessChild.h"
#include "GMPLoader.h"
#include "GeckoProfiler.h"
#include "base/histogram.h"
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
#define TARGET_SANDBOX_EXPORTS
#include "mozilla/sandboxing/loggingCallbacks.h"
#endif
#ifdef MOZ_IPDL_TESTS
#include "mozilla/_ipdltest/IPDLUnitTests.h"
#include "mozilla/_ipdltest/IPDLUnitTestProcessChild.h"
using mozilla::_ipdltest::IPDLUnitTestProcessChild;
#endif // ifdef MOZ_IPDL_TESTS
#ifdef MOZ_B2G_LOADER
#include "nsLocalFile.h"
#include "nsXREAppData.h"
#endif
using namespace mozilla;
using mozilla::ipc::BrowserProcessSubThread;
using mozilla::ipc::GeckoChildProcessHost;
using mozilla::ipc::IOThreadChild;
using mozilla::ipc::ProcessChild;
using mozilla::ipc::ScopedXREEmbed;
using mozilla::plugins::PluginProcessChild;
using mozilla::dom::ContentProcess;
using mozilla::dom::ContentParent;
using mozilla::dom::ContentChild;
using mozilla::gmp::GMPLoader;
using mozilla::gmp::CreateGMPLoader;
using mozilla::gmp::GMPProcessChild;
using mozilla::ipc::TestShellParent;
using mozilla::ipc::TestShellCommandParent;
using mozilla::ipc::XPCShellEnvironment;
using mozilla::startup::sChildProcessType;
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#ifdef XP_WIN
static const wchar_t kShellLibraryName[] = L"shell32.dll";
#endif
nsresult
XRE_LockProfileDirectory(nsIFile* aDirectory,
nsISupports* *aLockObject)
{
nsCOMPtr<nsIProfileLock> lock;
nsresult rv = NS_LockProfilePath(aDirectory, nullptr, nullptr,
getter_AddRefs(lock));
if (NS_SUCCEEDED(rv))
NS_ADDREF(*aLockObject = lock);
return rv;
}
static int32_t sInitCounter;
nsresult
XRE_InitEmbedding2(nsIFile *aLibXULDirectory,
nsIFile *aAppDirectory,
nsIDirectoryServiceProvider *aAppDirProvider)
{
// Initialize some globals to make nsXREDirProvider happy
static char* kNullCommandLine[] = { nullptr };
gArgv = kNullCommandLine;
gArgc = 0;
NS_ENSURE_ARG(aLibXULDirectory);
if (++sInitCounter > 1) // XXXbsmedberg is this really the right solution?
return NS_OK;
if (!aAppDirectory)
aAppDirectory = aLibXULDirectory;
nsresult rv;
new nsXREDirProvider; // This sets gDirServiceProvider
if (!gDirServiceProvider)
return NS_ERROR_OUT_OF_MEMORY;
rv = gDirServiceProvider->Initialize(aAppDirectory, aLibXULDirectory,
aAppDirProvider);
if (NS_FAILED(rv))
return rv;
rv = NS_InitXPCOM2(nullptr, aAppDirectory, gDirServiceProvider);
if (NS_FAILED(rv))
return rv;
// We do not need to autoregister components here. The CheckCompatibility()
// bits in nsAppRunner.cpp check for an invalidation flag in
// compatibility.ini.
// If the app wants to autoregister every time (for instance, if it's debug),
// it can do so after we return from this function.
nsCOMPtr<nsIObserver> startupNotifier
(do_CreateInstance(NS_APPSTARTUPNOTIFIER_CONTRACTID));
if (!startupNotifier)
return NS_ERROR_FAILURE;
startupNotifier->Observe(nullptr, APPSTARTUP_TOPIC, nullptr);
return NS_OK;
}
void
XRE_NotifyProfile()
{
NS_ASSERTION(gDirServiceProvider, "XRE_InitEmbedding was not called!");
gDirServiceProvider->DoStartup();
}
void
XRE_TermEmbedding()
{
if (--sInitCounter != 0)
return;
NS_ASSERTION(gDirServiceProvider,
"XRE_TermEmbedding without XRE_InitEmbedding");
gDirServiceProvider->DoShutdown();
NS_ShutdownXPCOM(nullptr);
delete gDirServiceProvider;
}
const char*
XRE_ChildProcessTypeToString(GeckoProcessType aProcessType)
{
return (aProcessType < GeckoProcessType_End) ?
kGeckoProcessTypeString[aProcessType] : nullptr;
}
namespace mozilla {
namespace startup {
GeckoProcessType sChildProcessType = GeckoProcessType_Default;
} // namespace startup
} // namespace mozilla
void
XRE_SetProcessType(const char* aProcessTypeString)
{
static bool called = false;
if (called) {
MOZ_CRASH();
}
called = true;
sChildProcessType = GeckoProcessType_Invalid;
for (int i = 0;
i < (int) ArrayLength(kGeckoProcessTypeString);
++i) {
if (!strcmp(kGeckoProcessTypeString[i], aProcessTypeString)) {
sChildProcessType = static_cast<GeckoProcessType>(i);
return;
}
}
}
#if defined(MOZ_CRASHREPORTER)
// FIXME/bug 539522: this out-of-place function is stuck here because
// IPDL wants access to this crashreporter interface, and
// crashreporter is built in such a way to make that awkward
bool
XRE_TakeMinidumpForChild(uint32_t aChildPid, nsIFile** aDump,
uint32_t* aSequence)
{
return CrashReporter::TakeMinidumpForChild(aChildPid, aDump, aSequence);
}
bool
XRE_SetRemoteExceptionHandler(const char* aPipe/*= 0*/)
{
#if defined(XP_WIN) || defined(XP_MACOSX)
return CrashReporter::SetRemoteExceptionHandler(nsDependentCString(aPipe));
#elif defined(OS_LINUX)
return CrashReporter::SetRemoteExceptionHandler();
#else
# error "OOP crash reporter unsupported on this platform"
#endif
}
#endif // if defined(MOZ_CRASHREPORTER)
#if defined(XP_WIN)
void
SetTaskbarGroupId(const nsString& aId)
{
typedef HRESULT (WINAPI * SetCurrentProcessExplicitAppUserModelIDPtr)(PCWSTR AppID);
SetCurrentProcessExplicitAppUserModelIDPtr funcAppUserModelID = nullptr;
HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
funcAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDPtr)
GetProcAddress(hDLL, "SetCurrentProcessExplicitAppUserModelID");
if (!funcAppUserModelID) {
::FreeLibrary(hDLL);
return;
}
if (FAILED(funcAppUserModelID(aId.get()))) {
NS_WARNING("SetCurrentProcessExplicitAppUserModelID failed for child process.");
}
if (hDLL)
::FreeLibrary(hDLL);
}
#endif
nsresult
XRE_InitChildProcess(int aArgc,
char* aArgv[],
GMPLoader* aGMPLoader)
{
NS_ENSURE_ARG_MIN(aArgc, 2);
NS_ENSURE_ARG_POINTER(aArgv);
NS_ENSURE_ARG_POINTER(aArgv[0]);
#ifdef HAS_DLL_BLOCKLIST
DllBlocklist_Initialize();
#endif
// This is needed by Telemetry to initialize histogram collection.
UniquePtr<base::StatisticsRecorder> statisticsRecorder =
MakeUnique<base::StatisticsRecorder>();
#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)
// On non-Fennec Gecko, the GMPLoader code resides in plugin-container,
// and we must forward it through to the GMP code here.
GMPProcessChild::SetGMPLoader(aGMPLoader);
#else
// On Fennec, the GMPLoader's code resides inside XUL (because for the time
// being GMPLoader relies upon NSPR, which we can't use in plugin-container
// on Android), so we create it here inside XUL and pass it to the GMP code.
nsAutoPtr<GMPLoader> loader(CreateGMPLoader(nullptr));
GMPProcessChild::SetGMPLoader(loader);
#endif
#if defined(XP_WIN)
// From the --attach-console support in nsNativeAppSupportWin.cpp, but
// here we are a content child process, so we always attempt to attach
// to the parent's (ie, the browser's) console.
// Try to attach console to the parent process.
// It will succeed when the parent process is a command line,
// so that stdio will be displayed in it.
if (AttachConsole(ATTACH_PARENT_PROCESS)) {
// Change std handles to refer to new console handles.
// Before doing so, ensure that stdout/stderr haven't been
// redirected to a valid file
if (_fileno(stdout) == -1 ||
_get_osfhandle(fileno(stdout)) == -1)
freopen("CONOUT$", "w", stdout);
// Merge stderr into CONOUT$ since there isn't any `CONERR$`.
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx
if (_fileno(stderr) == -1 ||
_get_osfhandle(fileno(stderr)) == -1)
freopen("CONOUT$", "w", stderr);
if (_fileno(stdin) == -1 || _get_osfhandle(fileno(stdin)) == -1)
freopen("CONIN$", "r", stdin);
}
#endif
// NB: This must be called before profiler_init
NS_LogInit();
mozilla::LogModule::Init();
char aLocal;
profiler_init(&aLocal);
PROFILER_LABEL("Startup", "XRE_InitChildProcess",
js::ProfileEntry::Category::OTHER);
// Complete 'task_t' exchange for Mac OS X. This structure has the same size
// regardless of architecture so we don't have any cross-arch issues here.
#ifdef XP_MACOSX
if (aArgc < 1)
return NS_ERROR_FAILURE;
const char* const mach_port_name = aArgv[--aArgc];
const int kTimeoutMs = 1000;
MachSendMessage child_message(0);
if (!child_message.AddDescriptor(MachMsgPortDescriptor(mach_task_self()))) {
NS_WARNING("child AddDescriptor(mach_task_self()) failed.");
return NS_ERROR_FAILURE;
}
ReceivePort child_recv_port;
mach_port_t raw_child_recv_port = child_recv_port.GetPort();
if (!child_message.AddDescriptor(MachMsgPortDescriptor(raw_child_recv_port))) {
NS_WARNING("Adding descriptor to message failed");
return NS_ERROR_FAILURE;
}
ReceivePort* ports_out_receiver = new ReceivePort();
if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_out_receiver->GetPort()))) {
NS_WARNING("Adding descriptor to message failed");
return NS_ERROR_FAILURE;
}
ReceivePort* ports_in_receiver = new ReceivePort();
if (!child_message.AddDescriptor(MachMsgPortDescriptor(ports_in_receiver->GetPort()))) {
NS_WARNING("Adding descriptor to message failed");
return NS_ERROR_FAILURE;
}
MachPortSender child_sender(mach_port_name);
kern_return_t err = child_sender.SendMessage(child_message, kTimeoutMs);
if (err != KERN_SUCCESS) {
NS_WARNING("child SendMessage() failed");
return NS_ERROR_FAILURE;
}
MachReceiveMessage parent_message;
err = child_recv_port.WaitForMessage(&parent_message, kTimeoutMs);
if (err != KERN_SUCCESS) {
NS_WARNING("child WaitForMessage() failed");
return NS_ERROR_FAILURE;
}
if (parent_message.GetTranslatedPort(0) == MACH_PORT_NULL) {
NS_WARNING("child GetTranslatedPort(0) failed");
return NS_ERROR_FAILURE;
}
err = task_set_bootstrap_port(mach_task_self(),
parent_message.GetTranslatedPort(0));
if (parent_message.GetTranslatedPort(1) == MACH_PORT_NULL) {
NS_WARNING("child GetTranslatedPort(1) failed");
return NS_ERROR_FAILURE;
}
MachPortSender* ports_out_sender = new MachPortSender(parent_message.GetTranslatedPort(1));
if (parent_message.GetTranslatedPort(2) == MACH_PORT_NULL) {
NS_WARNING("child GetTranslatedPort(2) failed");
return NS_ERROR_FAILURE;
}
MachPortSender* ports_in_sender = new MachPortSender(parent_message.GetTranslatedPort(2));
if (err != KERN_SUCCESS) {
NS_WARNING("child task_set_bootstrap_port() failed");
return NS_ERROR_FAILURE;
}
#endif
SetupErrorHandling(aArgv[0]);
#if defined(MOZ_CRASHREPORTER)
if (aArgc < 1)
return NS_ERROR_FAILURE;
const char* const crashReporterArg = aArgv[--aArgc];
# if defined(XP_WIN) || defined(XP_MACOSX)
// on windows and mac, |crashReporterArg| is the named pipe on which the
// server is listening for requests, or "-" if crash reporting is
// disabled.
if (0 != strcmp("-", crashReporterArg) &&
!XRE_SetRemoteExceptionHandler(crashReporterArg)) {
// Bug 684322 will add better visibility into this condition
NS_WARNING("Could not setup crash reporting\n");
}
# elif defined(OS_LINUX)
// on POSIX, |crashReporterArg| is "true" if crash reporting is
// enabled, false otherwise
if (0 != strcmp("false", crashReporterArg) &&
!XRE_SetRemoteExceptionHandler(nullptr)) {
// Bug 684322 will add better visibility into this condition
NS_WARNING("Could not setup crash reporting\n");
}
# else
# error "OOP crash reporting unsupported on this platform"
# endif
#endif // if defined(MOZ_CRASHREPORTER)
gArgv = aArgv;
gArgc = aArgc;
#ifdef MOZ_X11
XInitThreads();
#endif
#if MOZ_WIDGET_GTK == 2
XRE_GlibInit();
#endif
#if defined(MOZ_WIDGET_QT)
nsQAppInstance::AddRef();
#endif
#ifdef OS_POSIX
if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS") ||
PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
printf_stderr("\n\nCHILDCHILDCHILDCHILD\n debug me @ %d\n\n",
base::GetCurrentProcId());
sleep(30);
}
#elif defined(OS_WIN)
if (PR_GetEnv("MOZ_DEBUG_CHILD_PROCESS")) {
NS_DebugBreak(NS_DEBUG_BREAK,
"Invoking NS_DebugBreak() to debug child process",
nullptr, __FILE__, __LINE__);
} else if (PR_GetEnv("MOZ_DEBUG_CHILD_PAUSE")) {
printf_stderr("\n\nCHILDCHILDCHILDCHILD\n debug me @ %d\n\n",
base::GetCurrentProcId());
::Sleep(10000);
}
#endif
// child processes launched by GeckoChildProcessHost get this magic
// argument appended to their command lines
const char* const parentPIDString = aArgv[aArgc-1];
MOZ_ASSERT(parentPIDString, "NULL parent PID");
--aArgc;
char* end = 0;
base::ProcessId parentPID = strtol(parentPIDString, &end, 10);
MOZ_ASSERT(!*end, "invalid parent PID");
#ifdef XP_MACOSX
mozilla::ipc::SharedMemoryBasic::SetupMachMemory(parentPID, ports_in_receiver, ports_in_sender,
ports_out_sender, ports_out_receiver, true);
#endif
#if defined(XP_WIN)
// On Win7+, register the application user model id passed in by
// parent. This insures windows created by the container properly
// group with the parent app on the Win7 taskbar.
const char* const appModelUserId = aArgv[--aArgc];
if (appModelUserId) {
// '-' implies no support
if (*appModelUserId != '-') {
nsString appId;
appId.AssignWithConversion(nsDependentCString(appModelUserId));
// The version string is encased in quotes
appId.Trim(NS_LITERAL_CSTRING("\"").get());
// Set the id
SetTaskbarGroupId(appId);
}
}
#endif
base::AtExitManager exitManager;
NotificationService notificationService;
nsresult rv = XRE_InitCommandLine(aArgc, aArgv);
if (NS_FAILED(rv)) {
profiler_shutdown();
NS_LogTerm();
return NS_ERROR_FAILURE;
}
MessageLoop::Type uiLoopType;
switch (XRE_GetProcessType()) {
case GeckoProcessType_Content:
// Content processes need the XPCOM/chromium frankenventloop
uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD;
break;
case GeckoProcessType_GMPlugin:
uiLoopType = MessageLoop::TYPE_DEFAULT;
break;
default:
uiLoopType = MessageLoop::TYPE_UI;
break;
}
{
// This is a lexical scope for the MessageLoop below. We want it
// to go out of scope before NS_LogTerm() so that we don't get
// spurious warnings about XPCOM objects being destroyed from a
// static context.
// Associate this thread with a UI MessageLoop
MessageLoop uiMessageLoop(uiLoopType);
{
nsAutoPtr<ProcessChild> process;
#ifdef XP_WIN
mozilla::ipc::windows::InitUIThread();
#endif
switch (XRE_GetProcessType()) {
case GeckoProcessType_Default:
NS_RUNTIMEABORT("This makes no sense");
break;
case GeckoProcessType_Plugin:
process = new PluginProcessChild(parentPID);
break;
case GeckoProcessType_Content: {
process = new ContentProcess(parentPID);
// If passed in grab the application path for xpcom init
nsCString appDir;
for (int idx = aArgc; idx > 0; idx--) {
if (aArgv[idx] && !strcmp(aArgv[idx], "-appdir")) {
appDir.Assign(nsDependentCString(aArgv[idx+1]));
static_cast<ContentProcess*>(process.get())->SetAppDir(appDir);
break;
}
}
}
break;
case GeckoProcessType_IPDLUnitTest:
#ifdef MOZ_IPDL_TESTS
process = new IPDLUnitTestProcessChild(parentPID);
#else
NS_RUNTIMEABORT("rebuild with --enable-ipdl-tests");
#endif
break;
case GeckoProcessType_GMPlugin:
process = new gmp::GMPProcessChild(parentPID);
break;
default:
NS_RUNTIMEABORT("Unknown main thread class");
}
if (!process->Init()) {
profiler_shutdown();
NS_LogTerm();
return NS_ERROR_FAILURE;
}
#ifdef MOZ_CRASHREPORTER
#if defined(XP_WIN) || defined(XP_MACOSX)
CrashReporter::InitChildProcessTmpDir();
#endif
#endif
#if defined(XP_WIN)
// Set child processes up such that they will get killed after the
// chrome process is killed in cases where the user shuts the system
// down or logs off.
::SetProcessShutdownParameters(0x280 - 1, SHUTDOWN_NORETRY);
#endif
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
// We need to do this after the process has been initialised, as
// InitLoggingIfRequired may need access to prefs.
mozilla::sandboxing::InitLoggingIfRequired();
#endif
OverrideDefaultLocaleIfNeeded();
// Run the UI event loop on the main thread.
uiMessageLoop.MessageLoop::Run();
// Allow ProcessChild to clean up after itself before going out of
// scope and being deleted
process->CleanUp();
mozilla::Omnijar::CleanUp();
}
}
statisticsRecorder = nullptr;
profiler_shutdown();
NS_LogTerm();
return XRE_DeinitCommandLine();
}
MessageLoop*
XRE_GetIOMessageLoop()
{
if (sChildProcessType == GeckoProcessType_Default) {
return BrowserProcessSubThread::GetMessageLoop(BrowserProcessSubThread::IO);
}
return IOThreadChild::message_loop();
}
namespace {
class MainFunctionRunnable : public Runnable
{
public:
NS_DECL_NSIRUNNABLE
MainFunctionRunnable(MainFunction aFunction,
void* aData)
: mFunction(aFunction),
mData(aData)
{
NS_ASSERTION(aFunction, "Don't give me a null pointer!");
}
private:
MainFunction mFunction;
void* mData;
};
} /* anonymous namespace */
NS_IMETHODIMP
MainFunctionRunnable::Run()
{
mFunction(mData);
return NS_OK;
}
nsresult
XRE_InitParentProcess(int aArgc,
char* aArgv[],
MainFunction aMainFunction,
void* aMainFunctionData)
{
NS_ENSURE_ARG_MIN(aArgc, 1);
NS_ENSURE_ARG_POINTER(aArgv);
NS_ENSURE_ARG_POINTER(aArgv[0]);
ScopedXREEmbed embed;
gArgc = aArgc;
gArgv = aArgv;
nsresult rv = XRE_InitCommandLine(gArgc, gArgv);
if (NS_FAILED(rv))
return NS_ERROR_FAILURE;
{
embed.Start();
nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
if (aMainFunction) {
nsCOMPtr<nsIRunnable> runnable =
new MainFunctionRunnable(aMainFunction, aMainFunctionData);
NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
nsresult rv = NS_DispatchToCurrentThread(runnable);
NS_ENSURE_SUCCESS(rv, rv);
}
// Do event loop
if (NS_FAILED(appShell->Run())) {
NS_WARNING("Failed to run appshell");
return NS_ERROR_FAILURE;
}
}
return XRE_DeinitCommandLine();
}
#ifdef MOZ_IPDL_TESTS
//-----------------------------------------------------------------------------
// IPDL unit test
int
XRE_RunIPDLTest(int aArgc, char** aArgv)
{
if (aArgc < 2) {
fprintf(stderr, "TEST-UNEXPECTED-FAIL | <---> | insufficient #args, need at least 2\n");
return 1;
}
void* data = reinterpret_cast<void*>(aArgv[aArgc-1]);
nsresult rv =
XRE_InitParentProcess(
--aArgc, aArgv, mozilla::_ipdltest::IPDLUnitTestMain, data);
NS_ENSURE_SUCCESS(rv, 1);
return 0;
}
#endif // ifdef MOZ_IPDL_TESTS
nsresult
XRE_RunAppShell()
{
nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
NS_ENSURE_TRUE(appShell, NS_ERROR_FAILURE);
#if defined(XP_MACOSX)
{
// In content processes that want XPCOM (and hence want
// AppShell), we usually run our hybrid event loop through
// MessagePump::Run(), by way of nsBaseAppShell::Run(). The
// Cocoa nsAppShell impl, however, implements its own Run()
// that's unaware of MessagePump. That's all rather suboptimal,
// but oddly enough not a problem... usually.
//
// The problem with this setup comes during startup.
// XPCOM-in-subprocesses depends on IPC, e.g. to init the pref
// service, so we have to init IPC first. But, IPC also
// indirectly kinda-depends on XPCOM, because MessagePump
// schedules work from off-main threads (e.g. IO thread) by
// using NS_DispatchToMainThread(). If the IO thread receives a
// Message from the parent before nsThreadManager is
// initialized, then DispatchToMainThread() will fail, although
// MessagePump will remember the task. This race condition
// isn't a problem when appShell->Run() ends up in
// MessagePump::Run(), because MessagePump will immediate see it
// has work to do. It *is* a problem when we end up in [NSApp
// run], because it's not aware that MessagePump has work that
// needs to be processed; that was supposed to be signaled by
// nsIRunnable(s).
//
// So instead of hacking Cocoa nsAppShell or rewriting the
// event-loop system, we compromise here by processing any tasks
// that might have been enqueued on MessagePump, *before*
// MessagePump::ScheduleWork was able to successfully
// DispatchToMainThread().
MessageLoop* loop = MessageLoop::current();
bool couldNest = loop->NestableTasksAllowed();
loop->SetNestableTasksAllowed(true);
RefPtr<Runnable> task = new MessageLoop::QuitTask();
loop->PostTask(task.forget());
loop->Run();
loop->SetNestableTasksAllowed(couldNest);
}
#endif // XP_MACOSX
return appShell->Run();
}
void
XRE_ShutdownChildProcess()
{
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
#if defined(XP_MACOSX)
mozilla::ipc::SharedMemoryBasic::Shutdown();
#endif
mozilla::DebugOnly<MessageLoop*> ioLoop = XRE_GetIOMessageLoop();
MOZ_ASSERT(!!ioLoop, "Bad shutdown order");
// Quit() sets off the following chain of events
// (1) UI loop starts quitting
// (2) UI loop returns from Run() in XRE_InitChildProcess()
// (3) ProcessChild goes out of scope and terminates the IO thread
// (4) ProcessChild joins the IO thread
// (5) exit()
MessageLoop::current()->Quit();
#if defined(XP_MACOSX)
nsCOMPtr<nsIAppShell> appShell(do_GetService(kAppShellCID));
if (appShell) {
// On Mac, we might be only above nsAppShell::Run(), not
// MessagePump::Run(). See XRE_RunAppShell(). To account for
// that case, we fire off an Exit() here. If we were indeed
// above MessagePump::Run(), this Exit() is just superfluous.
appShell->Exit();
}
#endif // XP_MACOSX
}
namespace {
ContentParent* gContentParent; //long-lived, manually refcounted
TestShellParent* GetOrCreateTestShellParent()
{
if (!gContentParent) {
RefPtr<ContentParent> parent = ContentParent::GetNewOrUsedBrowserProcess();
parent.forget(&gContentParent);
} else if (!gContentParent->IsAlive()) {
return nullptr;
}
TestShellParent* tsp = gContentParent->GetTestShellSingleton();
if (!tsp) {
tsp = gContentParent->CreateTestShell();
}
return tsp;
}
} // namespace
bool
XRE_SendTestShellCommand(JSContext* aCx,
JSString* aCommand,
void* aCallback)
{
JS::RootedString cmd(aCx, aCommand);
TestShellParent* tsp = GetOrCreateTestShellParent();
NS_ENSURE_TRUE(tsp, false);
nsAutoJSString command;
NS_ENSURE_TRUE(command.init(aCx, cmd), false);
if (!aCallback) {
return tsp->SendExecuteCommand(command);
}
TestShellCommandParent* callback = static_cast<TestShellCommandParent*>(
tsp->SendPTestShellCommandConstructor(command));
NS_ENSURE_TRUE(callback, false);
JS::Value callbackVal = *reinterpret_cast<JS::Value*>(aCallback);
NS_ENSURE_TRUE(callback->SetCallback(aCx, callbackVal), false);
return true;
}
bool
XRE_ShutdownTestShell()
{
if (!gContentParent) {
return true;
}
bool ret = true;
if (gContentParent->IsAlive()) {
ret = gContentParent->DestroyTestShell(
gContentParent->GetTestShellSingleton());
}
NS_RELEASE(gContentParent);
return ret;
}
#ifdef MOZ_X11
void
XRE_InstallX11ErrorHandler()
{
#if (MOZ_WIDGET_GTK == 3)
InstallGdkErrorHandler();
#else
InstallX11ErrorHandler();
#endif
}
#endif
#ifdef MOZ_B2G_LOADER
extern const nsXREAppData* gAppData;
/**
* Preload static data of Gecko for B2G loader.
*
* This function is supposed to be called before XPCOM is initialized.
* For now, this function preloads
* - XPT interface Information
*/
void
XRE_ProcLoaderPreload(const char* aProgramDir, const nsXREAppData* aAppData)
{
void PreloadXPT(nsIFile *);
nsresult rv;
nsCOMPtr<nsIFile> omnijarFile;
rv = NS_NewNativeLocalFile(nsCString(aProgramDir),
true,
getter_AddRefs(omnijarFile));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
rv = omnijarFile->AppendNative(NS_LITERAL_CSTRING(NS_STRINGIFY(OMNIJAR_NAME)));
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
/*
* gAppData is required by nsXULAppInfo. The manifest parser
* evaluate flags with the information from nsXULAppInfo.
*/
gAppData = aAppData;
PreloadXPT(omnijarFile);
gAppData = nullptr;
}
#endif /* MOZ_B2G_LOADER */