Bug 1488679 - Use MOZ_APP_VERSION_DISPLAY for --version to show the full version r=glandium

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* 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/dom/ContentParent.h"#include"mozilla/dom/ContentChild.h"#include"mozilla/ipc/GeckoChildProcessHost.h"#include"mozilla/ArrayUtils.h"#include"mozilla/Assertions.h"#include"mozilla/Attributes.h"#include"mozilla/Components.h"#include"mozilla/FilePreferences.h"#include"mozilla/ChaosMode.h"#include"mozilla/CmdLineAndEnvUtils.h"#include"mozilla/IOInterposer.h"#include"mozilla/Likely.h"#include"mozilla/MemoryChecking.h"#include"mozilla/Poison.h"#include"mozilla/Preferences.h"#include"mozilla/Printf.h"#include"mozilla/ResultExtensions.h"#include"mozilla/ScopeExit.h"#include"mozilla/Services.h"#include"mozilla/Telemetry.h"#include"mozilla/intl/LocaleService.h"#include"mozilla/recordreplay/ParentIPC.h"#include"mozilla/JSONWriter.h"#include"nsAppRunner.h"#include"mozilla/XREAppData.h"#include"mozilla/Bootstrap.h"#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)# include "nsUpdateDriver.h"#endif#include"ProfileReset.h"#ifdef MOZ_INSTRUMENT_EVENT_LOOP# include "EventTracer.h"#endif#ifdef XP_MACOSX# include "nsVersionComparator.h"# include "MacLaunchHelper.h"# include "MacApplicationDelegate.h"# include "MacAutoreleasePool.h"// these are needed for sysctl# include <sys/types.h># include <sys/sysctl.h>#endif#include"prnetdb.h"#include"prprf.h"#include"prproces.h"#include"prenv.h"#include"prtime.h"#include"nsIAppShellService.h"#include"nsIAppStartup.h"#include"nsAppStartupNotifier.h"#include"nsIMutableArray.h"#include"nsICategoryManager.h"#include"nsIChromeRegistry.h"#include"nsCommandLine.h"#include"nsIComponentManager.h"#include"nsIComponentRegistrar.h"#include"nsIConsoleService.h"#include"nsIContentHandler.h"#include"nsIDialogParamBlock.h"#include"nsIDOMWindow.h"#include"mozilla/ModuleUtils.h"#include"nsIIOService.h"#include"nsIObserverService.h"#include"nsINativeAppSupport.h"#include"nsIPlatformInfo.h"#include"nsIProcess.h"#include"nsIProfileUnlocker.h"#include"nsIPromptService.h"#include"nsIPropertyBag2.h"#include"nsIServiceManager.h"#include"nsIStringBundle.h"#include"nsISupportsPrimitives.h"#include"nsIToolkitChromeRegistry.h"#include"nsIToolkitProfile.h"#include"nsToolkitProfileService.h"#include"nsIURI.h"#include"nsIURL.h"#include"nsIWindowCreator.h"#include"nsIWindowMediator.h"#include"nsIWindowWatcher.h"#include"nsIXULAppInfo.h"#include"nsIXULRuntime.h"#include"nsPIDOMWindow.h"#include"nsIBaseWindow.h"#include"nsIWidget.h"#include"nsIDocShell.h"#include"nsAppShellCID.h"#include"mozilla/scache/StartupCache.h"#include"gfxPlatform.h"#include"gfxPrefs.h"#include"mozilla/Unused.h"#ifdef XP_WIN# include "nsIWinAppHelper.h"# include <windows.h># include <intrin.h># include <math.h># include "cairo/cairo-features.h"# include "mozilla/WindowsDllBlocklist.h"# include "mozilla/WinHeaderOnlyUtils.h"# include "mozilla/mscom/MainThreadRuntime.h"# include "mozilla/widget/AudioSession.h"# if defined(MOZ_LAUNCHER_PROCESS)# include "mozilla/LauncherRegistryInfo.h"# endif# ifndef PROCESS_DEP_ENABLE# define PROCESS_DEP_ENABLE 0x1# endif#endif#if defined(MOZ_CONTENT_SANDBOX)# include "mozilla/SandboxSettings.h"# if (defined(XP_WIN) || defined(XP_MACOSX))# include "nsIUUIDGenerator.h"# endif#endif#ifdef ACCESSIBILITY# include "nsAccessibilityService.h"# if defined(XP_WIN)# include "mozilla/a11y/Compatibility.h"# include "mozilla/a11y/Platform.h"# endif#endif#include"nsCRT.h"#include"nsCOMPtr.h"#include"nsDirectoryServiceDefs.h"#include"nsDirectoryServiceUtils.h"#include"nsEmbedCID.h"#include"nsNetUtil.h"#include"nsReadableUtils.h"#include"nsXPCOM.h"#include"nsXPCOMCIDInternal.h"#include"nsString.h"#include"nsPrintfCString.h"#include"nsVersionComparator.h"#include"nsAppDirectoryServiceDefs.h"#include"nsXULAppAPI.h"#include"nsXREDirProvider.h"#include"nsINIParser.h"#include"mozilla/Omnijar.h"#include"mozilla/StartupTimeline.h"#include"mozilla/LateWriteChecks.h"#include<stdlib.h>#include<locale.h>#ifdef XP_UNIX# include <errno.h># include <pwd.h># include <string.h># include <sys/resource.h># include <sys/stat.h># include <unistd.h>#endif#ifdef XP_WIN# include <process.h># include <shlobj.h># include "mozilla/WinDllServices.h"# include "nsThreadUtils.h"# include <comdef.h># include <wbemidl.h># include "WinUtils.h"#endif#ifdef XP_MACOSX# include "nsILocalFileMac.h"# include "nsCommandLineServiceMac.h"#endif// for X remote support#if defined(MOZ_WIDGET_GTK)# include "XRemoteClient.h"# include "nsIRemoteService.h"# include "nsProfileLock.h"# include "SpecialSystemDirectory.h"# include <sched.h># ifdef MOZ_ENABLE_DBUS# include "DBusRemoteClient.h"# endif// Time to wait for the remoting service to start# define MOZ_XREMOTE_START_TIMEOUT_SEC 5#endif#if defined(DEBUG) && defined(XP_WIN32)# include <malloc.h>#endif#if defined(XP_MACOSX)# include <Carbon/Carbon.h>#endif#ifdef DEBUG# include "mozilla/Logging.h"#endif#ifdef MOZ_JPROF# include "jprof.h"#endif#include"nsExceptionHandler.h"#include"nsICrashReporter.h"#define NS_CRASHREPORTER_CONTRACTID "@mozilla.org/toolkit/crash-reporter;1"#include"nsIPrefService.h"#include"nsIMemoryInfoDumper.h"#if defined(XP_LINUX) && !defined(ANDROID)# include "mozilla/widget/LSBUtils.h"#endif#include"base/command_line.h"#include"GTestRunner.h"#ifdef MOZ_WIDGET_ANDROID# include "GeneratedJNIWrappers.h"#endif#if defined(MOZ_SANDBOX)# if defined(XP_LINUX) && !defined(ANDROID)# include "mozilla/SandboxInfo.h"# elif defined(XP_WIN)# include "sandboxBroker.h"# include "sandboxPermissions.h"# endif#endif#ifdef MOZ_CODE_COVERAGE# include "mozilla/CodeCoverageHandler.h"#endif#include"mozilla/mozalloc_oom.h"#include"SafeMode.h"externuint32_tgRestartMode;externvoidInstallSignalHandlers(constchar*ProgramName);#define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")#define FILE_INVALIDATE_CACHES NS_LITERAL_CSTRING(".purgecaches")#define FILE_STARTUP_INCOMPLETE NS_LITERAL_STRING(".startup-incomplete")intgArgc;char**gArgv;#include"buildid.h"staticconstchargToolkitVersion[]=NS_STRINGIFY(GRE_MILESTONE);staticconstchargToolkitBuildID[]=NS_STRINGIFY(MOZ_BUILDID);staticnsIProfileLock*gProfileLock;intgRestartArgc;char**gRestartArgv;// If gRestartedByOS is set, we were automatically restarted by the OS.boolgRestartedByOS=false;boolgIsGtest=false;nsStringgAbsoluteArgv0Path;#if defined(MOZ_WIDGET_GTK)# include <glib.h># if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING)# define CLEANUP_MEMORY 1# define PANGO_ENABLE_BACKEND# include <pango/pangofc-fontmap.h># endif# include <gtk/gtk.h># ifdef MOZ_WAYLAND# include <gdk/gdkwayland.h># endif# ifdef MOZ_X11# include <gdk/gdkx.h># endif /* MOZ_X11 */# include "nsGTKToolkit.h"# include <fontconfig/fontconfig.h>#endif#include"BinaryPath.h"#ifdef MOZ_LINKERextern"C"MFBT_APIboolIsSignalHandlingBroken();#endif#ifdef FUZZING# include "FuzzerRunner.h"namespacemozilla{FuzzerRunner*fuzzerRunner=0;}// namespace mozilla# ifdef LIBFUZZERvoidXRE_LibFuzzerSetDriver(LibFuzzerDriveraDriver){mozilla::fuzzerRunner->setParams(aDriver);}# endif#endif // FUZZINGnamespacemozilla{int(*RunGTest)(int*,char**)=0;}// namespace mozillausingnamespacemozilla;usingnamespacemozilla::startup;usingmozilla::Unused;usingmozilla::dom::ContentChild;usingmozilla::dom::ContentParent;usingmozilla::intl::LocaleService;usingmozilla::scache::StartupCache;// Save the given word to the specified environment variable.staticvoidMOZ_NEVER_INLINESaveWordToEnv(constchar*name,constnsACString&word){char*expr=Smprintf("%s=%s",name,PromiseFlatCString(word).get()).release();if(expr)PR_SetEnv(expr);// We intentionally leak |expr| here since it is required by PR_SetEnv.}// Save the path of the given file to the specified environment variable.staticvoidSaveFileToEnv(constchar*name,nsIFile*file){#ifdef XP_WINnsAutoStringpath;file->GetPath(path);SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(),path.get());#elsensAutoCStringpath;file->GetNativePath(path);SaveWordToEnv(name,path);#endif}// Save the path of the given file to the specified environment variable// provided the environment variable does not have a value.staticvoidSaveFileToEnvIfUnset(constchar*name,nsIFile*file){if(!EnvHasValue(name))SaveFileToEnv(name,file);}staticboolgIsExpectedExit=false;voidMozExpectedExit(){gIsExpectedExit=true;}/** * Runs atexit() to catch unexpected exit from 3rd party libraries like the * Intel graphics driver calling exit in an error condition. When they * call exit() to report an error we won't shutdown correctly and wont catch * the issue with our crash reporter. */staticvoidUnexpectedExit(){if(!gIsExpectedExit){gIsExpectedExit=true;// Don't risk re-entrency issues when crashing.MOZ_CRASH("Exit called by third party code.");}}/** * Output a string to the user. This method is really only meant to be used to * output last-ditch error messages designed for developers NOT END USERS. * * @param isError * Pass true to indicate severe errors. * @param fmt * printf-style format string followed by arguments. */staticMOZ_FORMAT_PRINTF(2,3)voidOutput(boolisError,constchar*fmt,...){va_listap;va_start(ap,fmt);#if defined(XP_WIN) && !MOZ_WINCONSOLESmprintfPointermsg=mozilla::Vsmprintf(fmt,ap);if(msg){UINTflags=MB_OK;if(isError)flags|=MB_ICONERROR;elseflags|=MB_ICONINFORMATION;wchar_twide_msg[1024];MultiByteToWideChar(CP_ACP,0,msg.get(),-1,wide_msg,sizeof(wide_msg)/sizeof(wchar_t));MessageBoxW(nullptr,wide_msg,L"XULRunner",flags);}#elsevfprintf(stderr,fmt,ap);#endifva_end(ap);}enumRemoteResult{REMOTE_NOT_FOUND=0,REMOTE_FOUND=1,REMOTE_ARG_BAD=2};/** * Check for a commandline flag. If the flag takes a parameter, the * parameter is returned in aParam. Flags may be in the form -arg or * --arg (or /arg on win32). * * @param aArg the parameter to check. Must be lowercase. * @param aParam if non-null, the -arg <data> will be stored in this pointer. * This is *not* allocated, but rather a pointer to the argv data. * @param aFlags flags @see CheckArgFlag */staticArgResultCheckArg(constchar*aArg,constchar**aParam=nullptr,CheckArgFlagaFlags=CheckArgFlag::RemoveArg){MOZ_ASSERT(gArgv,"gArgv must be initialized before CheckArg()");returnCheckArg(gArgc,gArgv,aArg,aParam,aFlags);}/** * Check for a commandline flag. Ignore data that's passed in with the flag. * Flags may be in the form -arg or --arg (or /arg on win32). * Will not remove flag if found. * * @param aArg the parameter to check. Must be lowercase. */staticArgResultCheckArgExists(constchar*aArg){returnCheckArg(aArg,nullptr,CheckArgFlag::None);}#if defined(XP_WIN)/** * Check for a commandline flag from the windows shell and remove it from the * argv used when restarting. Flags MUST be in the form -arg. * * @param aArg the parameter to check. Must be lowercase. */staticArgResultCheckArgShell(constchar*aArg){char**curarg=gRestartArgv+1;// skip argv[0]while(*curarg){char*arg=curarg[0];if(arg[0]=='-'){++arg;if(strimatch(aArg,arg)){do{*curarg=*(curarg+1);++curarg;}while(*curarg);--gRestartArgc;returnARG_FOUND;}}++curarg;}returnARG_NONE;}/** * Enabled Native App Support to process DDE messages when the app needs to * restart and the app has been launched by the Windows shell to open an url. * When aWait is false this will process the DDE events manually. This prevents * Windows from displaying an error message due to the DDE message not being * acknowledged. */staticvoidProcessDDE(nsINativeAppSupport*aNative,boolaWait){// When the app is launched by the windows shell the windows shell// expects the app to be available for DDE messages and if it isn't// windows displays an error dialog. To prevent the error the DDE server// is enabled and pending events are processed when the app needs to// restart after it was launched by the shell with the requestpending// argument. The requestpending pending argument is removed to// differentiate it from being launched when an app restart is not// required.ArgResultar;ar=CheckArgShell("requestpending");if(ar==ARG_FOUND){aNative->Enable();// enable win32 DDE responsesif(aWait){// This is just a guesstimate based on testing different values.// If count is 8 or less windows will display an error dialog.int32_tcount=20;SpinEventLoopUntil([&](){return--count<0;});}}}#endifboolgSafeMode=false;/** * The nsXULAppInfo object implements nsIFactory so that it can be its own * singleton. */classnsXULAppInfo:publicnsIXULAppInfo,publicnsIObserver,#ifdef XP_WINpublicnsIWinAppHelper,#endifpublicnsICrashReporter,publicnsIFinishDumpingCallback,publicnsIXULRuntime{public:constexprnsXULAppInfo(){}NS_DECL_ISUPPORTS_INHERITEDNS_DECL_NSIPLATFORMINFONS_DECL_NSIXULAPPINFONS_DECL_NSIXULRUNTIMENS_DECL_NSIOBSERVERNS_DECL_NSICRASHREPORTERNS_DECL_NSIFINISHDUMPINGCALLBACK#ifdef XP_WINNS_DECL_NSIWINAPPHELPER#endif};NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports,nsIXULRuntime)NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)NS_INTERFACE_MAP_ENTRY(nsIObserver)#ifdef XP_WINNS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)#endifNS_INTERFACE_MAP_ENTRY(nsICrashReporter)NS_INTERFACE_MAP_ENTRY(nsIFinishDumpingCallback)NS_INTERFACE_MAP_ENTRY(nsIPlatformInfo)NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo,gAppData||XRE_IsContentProcess())NS_INTERFACE_MAP_ENDNS_IMETHODIMP_(MozExternalRefCountType)nsXULAppInfo::AddRef(){return1;}NS_IMETHODIMP_(MozExternalRefCountType)nsXULAppInfo::Release(){return1;}NS_IMETHODIMPnsXULAppInfo::GetVendor(nsACString&aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aResult=cc->GetAppInfo().vendor;returnNS_OK;}aResult.Assign(gAppData->vendor);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetName(nsACString&aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aResult=cc->GetAppInfo().name;returnNS_OK;}aResult.Assign(gAppData->name);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetID(nsACString&aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aResult=cc->GetAppInfo().ID;returnNS_OK;}aResult.Assign(gAppData->ID);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetVersion(nsACString&aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aResult=cc->GetAppInfo().version;returnNS_OK;}aResult.Assign(gAppData->version);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetPlatformVersion(nsACString&aResult){aResult.Assign(gToolkitVersion);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetAppBuildID(nsACString&aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aResult=cc->GetAppInfo().buildID;returnNS_OK;}aResult.Assign(gAppData->buildID);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetPlatformBuildID(nsACString&aResult){aResult.Assign(gToolkitBuildID);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetUAName(nsACString&aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aResult=cc->GetAppInfo().UAName;returnNS_OK;}aResult.Assign(gAppData->UAName);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetSourceURL(nsACString&aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aResult=cc->GetAppInfo().sourceURL;returnNS_OK;}aResult.Assign(gAppData->sourceURL);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetLogConsoleErrors(bool*aResult){*aResult=gLogConsoleErrors;returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::SetLogConsoleErrors(boolaValue){gLogConsoleErrors=aValue;returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetInSafeMode(bool*aResult){*aResult=gSafeMode;returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetOS(nsACString&aResult){aResult.AssignLiteral(OS_TARGET);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetXPCOMABI(nsACString&aResult){#ifdef TARGET_XPCOM_ABIaResult.AssignLiteral(TARGET_XPCOM_ABI);returnNS_OK;#elsereturnNS_ERROR_NOT_AVAILABLE;#endif}NS_IMETHODIMPnsXULAppInfo::GetWidgetToolkit(nsACString&aResult){aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);returnNS_OK;}// Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,// is synchronized with the const unsigned longs defined in// xpcom/system/nsIXULRuntime.idl.#define SYNC_ENUMS(a, b) \ static_assert(nsIXULRuntime::PROCESS_TYPE_##a == \ static_cast<int>(GeckoProcessType_##b), \ "GeckoProcessType in nsXULAppAPI.h not synchronized with " \ "nsIXULRuntime.idl");SYNC_ENUMS(DEFAULT,Default)SYNC_ENUMS(PLUGIN,Plugin)SYNC_ENUMS(CONTENT,Content)SYNC_ENUMS(IPDLUNITTEST,IPDLUnitTest)SYNC_ENUMS(GMPLUGIN,GMPlugin)SYNC_ENUMS(GPU,GPU)SYNC_ENUMS(VR,VR)SYNC_ENUMS(RDD,RDD)SYNC_ENUMS(SOCKET,Socket)// .. and ensure that that is all of them:static_assert(GeckoProcessType_Socket+1==GeckoProcessType_End,"Did not find the final GeckoProcessType");NS_IMETHODIMPnsXULAppInfo::GetProcessType(uint32_t*aResult){NS_ENSURE_ARG_POINTER(aResult);*aResult=XRE_GetProcessType();returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetProcessID(uint32_t*aResult){#ifdef XP_WIN*aResult=GetCurrentProcessId();#else*aResult=getpid();#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetUniqueProcessID(uint64_t*aResult){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();*aResult=cc->GetID();}else{*aResult=0;}returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetRemoteType(nsAString&aRemoteType){if(XRE_IsContentProcess()){ContentChild*cc=ContentChild::GetSingleton();aRemoteType.Assign(cc->GetRemoteType());}else{SetDOMStringToNull(aRemoteType);}returnNS_OK;}staticboolgBrowserTabsRemoteAutostart=false;staticuint64_tgBrowserTabsRemoteStatus=0;staticboolgBrowserTabsRemoteAutostartInitialized=false;NS_IMETHODIMPnsXULAppInfo::Observe(nsISupports*aSubject,constchar*aTopic,constchar16_t*aData){if(!nsCRT::strcmp(aTopic,"getE10SBlocked")){nsCOMPtr<nsISupportsPRUint64>ret=do_QueryInterface(aSubject);if(!ret)returnNS_ERROR_FAILURE;ret->SetData(gBrowserTabsRemoteStatus);returnNS_OK;}returnNS_ERROR_FAILURE;}NS_IMETHODIMPnsXULAppInfo::GetBrowserTabsRemoteAutostart(bool*aResult){*aResult=BrowserTabsRemoteAutostart();returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetMaxWebProcessCount(uint32_t*aResult){*aResult=mozilla::GetMaxWebProcessCount();returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetAccessibilityEnabled(bool*aResult){#ifdef ACCESSIBILITY*aResult=GetAccService()!=nullptr;#else*aResult=false;#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetAccessibleHandlerUsed(bool*aResult){#if defined(ACCESSIBILITY) && defined(XP_WIN)*aResult=Preferences::GetBool("accessibility.handler.enabled",false)&&a11y::IsHandlerRegistered();#else*aResult=false;#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetAccessibilityInstantiator(nsAString&aInstantiator){#if defined(ACCESSIBILITY) && defined(XP_WIN)if(!GetAccService()){aInstantiator=NS_LITERAL_STRING("");returnNS_OK;}nsAutoStringipClientInfo;a11y::Compatibility::GetHumanReadableConsumersStr(ipClientInfo);aInstantiator.Append(ipClientInfo);aInstantiator.AppendLiteral("|");nsCOMPtr<nsIFile>oopClientExe;if(a11y::GetInstantiator(getter_AddRefs(oopClientExe))){nsAutoStringoopClientInfo;if(NS_SUCCEEDED(oopClientExe->GetPath(oopClientInfo))){aInstantiator.Append(oopClientInfo);}}#elseaInstantiator=NS_LITERAL_STRING("");#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetShouldBlockIncompatJaws(bool*aResult){*aResult=false;#if defined(ACCESSIBILITY) && defined(XP_WIN)*aResult=mozilla::a11y::Compatibility::IsOldJAWS();#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetIs64Bit(bool*aResult){#ifdef HAVE_64BIT_BUILD*aResult=true;#else*aResult=false;#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::EnsureContentProcess(){if(!XRE_IsParentProcess())returnNS_ERROR_NOT_AVAILABLE;RefPtr<ContentParent>unused=ContentParent::GetNewOrUsedBrowserProcess(nullptr,NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::InvalidateCachesOnRestart(){nsCOMPtr<nsIFile>file;nsresultrv=NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,getter_AddRefs(file));if(NS_FAILED(rv))returnrv;if(!file)returnNS_ERROR_NOT_AVAILABLE;file->AppendNative(FILE_COMPATIBILITY_INFO);nsINIParserparser;rv=parser.Init(file);if(NS_FAILED(rv)){// This fails if compatibility.ini is not there, so we'll// flush the caches on the next restart anyways.returnNS_OK;}nsAutoCStringbuf;rv=parser.GetString("Compatibility","InvalidateCaches",buf);if(NS_FAILED(rv)){PRFileDesc*fd;rv=file->OpenNSPRFileDesc(PR_RDWR|PR_APPEND,0600,&fd);if(NS_FAILED(rv)){NS_ERROR("could not create output stream");returnNS_ERROR_NOT_AVAILABLE;}staticconstcharkInvalidationHeader[]=NS_LINEBREAK"InvalidateCaches=1"NS_LINEBREAK;PR_Write(fd,kInvalidationHeader,sizeof(kInvalidationHeader)-1);PR_Close(fd);}returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetReplacedLockTime(PRTime*aReplacedLockTime){if(!gProfileLock)returnNS_ERROR_NOT_AVAILABLE;gProfileLock->GetReplacedLockTime(aReplacedLockTime);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetIsReleaseOrBeta(bool*aResult){#ifdef RELEASE_OR_BETA*aResult=true;#else*aResult=false;#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetIsOfficialBranding(bool*aResult){#ifdef MOZ_OFFICIAL_BRANDING*aResult=true;#else*aResult=false;#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetDefaultUpdateChannel(nsACString&aResult){aResult.AssignLiteral(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetDistributionID(nsACString&aResult){aResult.AssignLiteral(MOZ_DISTRIBUTION_ID);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetWindowsDLLBlocklistStatus(bool*aResult){#if defined(HAS_DLL_BLOCKLIST)*aResult=DllBlocklist_CheckStatus();#else*aResult=false;#endifreturnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetRestartedByOS(bool*aResult){*aResult=gRestartedByOS;returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetLauncherProcessState(uint32_t*aResult){#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)LauncherRegistryInfolauncherInfo;LauncherResult<LauncherRegistryInfo::EnabledState>state=launcherInfo.IsEnabled();if(state.isErr()){returnNS_ERROR_UNEXPECTED;}*aResult=static_cast<uint32_t>(state.unwrap());returnNS_OK;#elsereturnNS_ERROR_NOT_AVAILABLE;#endif}#ifdef XP_WIN// Matches the enum in WinNT.h for the Vista SDK but renamed so that we can// safely build with the Vista SDK and without it.typedefenum{VistaTokenElevationTypeDefault=1,VistaTokenElevationTypeFull,VistaTokenElevationTypeLimited}VISTA_TOKEN_ELEVATION_TYPE;// avoid collision with TokeElevationType enum in WinNT.h// of the Vista SDK# define VistaTokenElevationType static_cast<TOKEN_INFORMATION_CLASS>(18)NS_IMETHODIMPnsXULAppInfo::GetUserCanElevate(bool*aUserCanElevate){HANDLEhToken;VISTA_TOKEN_ELEVATION_TYPEelevationType;DWORDdwSize;if(!OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&hToken)||!GetTokenInformation(hToken,VistaTokenElevationType,&elevationType,sizeof(elevationType),&dwSize)){*aUserCanElevate=false;}else{// The possible values returned for elevationType and their meanings are:// TokenElevationTypeDefault: The token does not have a linked token// (e.g. UAC disabled or a standard user, so they can't be elevated)// TokenElevationTypeFull: The token is linked to an elevated token// (e.g. UAC is enabled and the user is already elevated so they can't// be elevated again)// TokenElevationTypeLimited: The token is linked to a limited token// (e.g. UAC is enabled and the user is not elevated, so they can be// elevated)*aUserCanElevate=(elevationType==VistaTokenElevationTypeLimited);}if(hToken)CloseHandle(hToken);returnNS_OK;}#endifNS_IMETHODIMPnsXULAppInfo::GetEnabled(bool*aEnabled){*aEnabled=CrashReporter::GetEnabled();returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::SetEnabled(boolaEnabled){if(aEnabled){if(CrashReporter::GetEnabled()){// no point in erroring for double-enablingreturnNS_OK;}nsCOMPtr<nsIFile>greBinDir;NS_GetSpecialDirectory(NS_GRE_BIN_DIR,getter_AddRefs(greBinDir));if(!greBinDir){returnNS_ERROR_FAILURE;}nsCOMPtr<nsIFile>xreBinDirectory=greBinDir;if(!xreBinDirectory){returnNS_ERROR_FAILURE;}returnCrashReporter::SetExceptionHandler(xreBinDirectory,true);}if(!CrashReporter::GetEnabled()){// no point in erroring for double-disablingreturnNS_OK;}returnCrashReporter::UnsetExceptionHandler();}NS_IMETHODIMPnsXULAppInfo::GetServerURL(nsIURL**aServerURL){NS_ENSURE_ARG_POINTER(aServerURL);if(!CrashReporter::GetEnabled())returnNS_ERROR_NOT_INITIALIZED;nsAutoCStringdata;if(!CrashReporter::GetServerURL(data)){returnNS_ERROR_FAILURE;}nsCOMPtr<nsIURI>uri;NS_NewURI(getter_AddRefs(uri),data);if(!uri)returnNS_ERROR_FAILURE;nsCOMPtr<nsIURL>url;url=do_QueryInterface(uri);NS_ADDREF(*aServerURL=url);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::SetServerURL(nsIURL*aServerURL){boolschemeOk;// only allow https or http URLsnsresultrv=aServerURL->SchemeIs("https",&schemeOk);NS_ENSURE_SUCCESS(rv,rv);if(!schemeOk){rv=aServerURL->SchemeIs("http",&schemeOk);NS_ENSURE_SUCCESS(rv,rv);if(!schemeOk)returnNS_ERROR_INVALID_ARG;}nsAutoCStringspec;rv=aServerURL->GetSpec(spec);NS_ENSURE_SUCCESS(rv,rv);returnCrashReporter::SetServerURL(spec);}NS_IMETHODIMPnsXULAppInfo::GetMinidumpPath(nsIFile**aMinidumpPath){if(!CrashReporter::GetEnabled())returnNS_ERROR_NOT_INITIALIZED;nsAutoStringpath;if(!CrashReporter::GetMinidumpPath(path))returnNS_ERROR_FAILURE;nsresultrv=NS_NewLocalFile(path,false,aMinidumpPath);NS_ENSURE_SUCCESS(rv,rv);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::SetMinidumpPath(nsIFile*aMinidumpPath){nsAutoStringpath;nsresultrv=aMinidumpPath->GetPath(path);NS_ENSURE_SUCCESS(rv,rv);returnCrashReporter::SetMinidumpPath(path);}NS_IMETHODIMPnsXULAppInfo::GetMinidumpForID(constnsAString&aId,nsIFile**aMinidump){if(!CrashReporter::GetMinidumpForID(aId,aMinidump)){returnNS_ERROR_FILE_NOT_FOUND;}returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::GetExtraFileForID(constnsAString&aId,nsIFile**aExtraFile){if(!CrashReporter::GetExtraFileForID(aId,aExtraFile)){returnNS_ERROR_FILE_NOT_FOUND;}returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::AnnotateCrashReport(constnsACString&key,constnsACString&data){CrashReporter::Annotationannotation;if(!AnnotationFromString(annotation,PromiseFlatCString(key).get())){returnNS_ERROR_INVALID_ARG;}returnCrashReporter::AnnotateCrashReport(annotation,data);}NS_IMETHODIMPnsXULAppInfo::RemoveCrashReportAnnotation(constnsACString&key){CrashReporter::Annotationannotation;if(!AnnotationFromString(annotation,PromiseFlatCString(key).get())){returnNS_ERROR_INVALID_ARG;}returnCrashReporter::RemoveCrashReportAnnotation(annotation);}NS_IMETHODIMPnsXULAppInfo::IsAnnotationWhitelistedForPing(constnsACString&aValue,bool*aIsWhitelisted){CrashReporter::Annotationannotation;if(!AnnotationFromString(annotation,PromiseFlatCString(aValue).get())){returnNS_ERROR_INVALID_ARG;}*aIsWhitelisted=CrashReporter::IsAnnotationWhitelistedForPing(annotation);returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::AppendAppNotesToCrashReport(constnsACString&data){returnCrashReporter::AppendAppNotesToCrashReport(data);}NS_IMETHODIMPnsXULAppInfo::RegisterAppMemory(uint64_tpointer,uint64_tlen){returnCrashReporter::RegisterAppMemory((void*)pointer,len);}NS_IMETHODIMPnsXULAppInfo::WriteMinidumpForException(void*aExceptionInfo){#ifdef XP_WIN32returnCrashReporter::WriteMinidumpForException(static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));#elsereturnNS_ERROR_NOT_IMPLEMENTED;#endif}NS_IMETHODIMPnsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void*aException){#ifdef XP_MACOSXreturnCrashReporter::AppendObjCExceptionInfoToAppNotes(aException);#elsereturnNS_ERROR_NOT_IMPLEMENTED;#endif}NS_IMETHODIMPnsXULAppInfo::GetSubmitReports(bool*aEnabled){returnCrashReporter::GetSubmitReports(aEnabled);}NS_IMETHODIMPnsXULAppInfo::SetSubmitReports(boolaEnabled){returnCrashReporter::SetSubmitReports(aEnabled);}NS_IMETHODIMPnsXULAppInfo::UpdateCrashEventsDir(){CrashReporter::UpdateCrashEventsDir();returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::SaveMemoryReport(){if(!CrashReporter::GetEnabled()){returnNS_ERROR_NOT_INITIALIZED;}nsCOMPtr<nsIFile>file;nsresultrv=CrashReporter::GetDefaultMemoryReportFile(getter_AddRefs(file));if(NS_WARN_IF(NS_FAILED(rv))){returnrv;}nsStringpath;file->GetPath(path);nsCOMPtr<nsIMemoryInfoDumper>dumper=do_GetService("@mozilla.org/memory-info-dumper;1");if(NS_WARN_IF(!dumper)){returnNS_ERROR_UNEXPECTED;}rv=dumper->DumpMemoryReportsToNamedFile(path,this,file,true/* anonymize */);if(NS_WARN_IF(NS_FAILED(rv))){returnrv;}returnNS_OK;}NS_IMETHODIMPnsXULAppInfo::SetTelemetrySessionId(constnsACString&id){CrashReporter::SetTelemetrySessionId(id);returnNS_OK;}// This method is from nsIFInishDumpingCallback.NS_IMETHODIMPnsXULAppInfo::Callback(nsISupports*aData){nsCOMPtr<nsIFile>file=do_QueryInterface(aData);MOZ_ASSERT(file);CrashReporter::SetMemoryReportFile(file);returnNS_OK;}staticconstnsXULAppInfokAppInfo;staticnsresultAppInfoConstructor(nsISupports*aOuter,REFNSIIDaIID,void**aResult){NS_ENSURE_NO_AGGREGATION(aOuter);returnconst_cast<nsXULAppInfo*>(&kAppInfo)->QueryInterface(aIID,aResult);}boolgLogConsoleErrors=false;#define NS_ENSURE_TRUE_LOG(x, ret) \ PR_BEGIN_MACRO \ if (MOZ_UNLIKELY(!(x))) { \ NS_WARNING("NS_ENSURE_TRUE(" #x ") failed"); \ gLogConsoleErrors = true; \ return ret; \ } \ PR_END_MACRO#define NS_ENSURE_SUCCESS_LOG(res, ret) \ NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)/** * Because we're starting/stopping XPCOM several times in different scenarios, * this class is a stack-based critter that makes sure that XPCOM is shut down * during early returns. */classScopedXPCOMStartup{public:ScopedXPCOMStartup():mServiceManager(nullptr){}~ScopedXPCOMStartup();nsresultInitialize();nsresultSetWindowCreator(nsINativeAppSupport*native);private:nsIServiceManager*mServiceManager;staticnsINativeAppSupport*gNativeAppSupport;friendalready_AddRefed<nsINativeAppSupport>NS_GetNativeAppSupport();};ScopedXPCOMStartup::~ScopedXPCOMStartup(){NS_IF_RELEASE(gNativeAppSupport);if(mServiceManager){#ifdef XP_MACOSX// On OS X, we need a pool to catch cocoa objects that are autoreleased// during teardown.mozilla::MacAutoreleasePoolpool;#endifnsCOMPtr<nsIAppStartup>appStartup(components::AppStartup::Service());if(appStartup)appStartup->DestroyHiddenWindow();gDirServiceProvider->DoShutdown();PROFILER_ADD_MARKER("Shutdown early",OTHER);WriteConsoleLog();NS_ShutdownXPCOM(mServiceManager);mServiceManager=nullptr;}}// {95d89e3e-a169-41a3-8e56-719978e15b12}#define APPINFO_CID \ { \ 0x95d89e3e, 0xa169, 0x41a3, { \ 0x8e, 0x56, 0x71, 0x99, 0x78, 0xe1, 0x5b, 0x12 \ } \ }// {5F5E59CE-27BC-47eb-9D1F-B09CA9049836}staticconstnsCIDkProfileServiceCID={0x5f5e59ce,0x27bc,0x47eb,{0x9d,0x1f,0xb0,0x9c,0xa9,0x4,0x98,0x36}};staticalready_AddRefed<nsIFactory>ProfileServiceFactoryConstructor(constmozilla::Module&module,constmozilla::Module::CIDEntry&entry){nsCOMPtr<nsIFactory>factory;NS_NewToolkitProfileFactory(getter_AddRefs(factory));returnfactory.forget();}NS_DEFINE_NAMED_CID(APPINFO_CID);staticconstmozilla::Module::CIDEntrykXRECIDs[]={{&kAPPINFO_CID,false,nullptr,AppInfoConstructor},{&kProfileServiceCID,false,ProfileServiceFactoryConstructor,nullptr},{nullptr}};staticconstmozilla::Module::ContractIDEntrykXREContracts[]={{XULAPPINFO_SERVICE_CONTRACTID,&kAPPINFO_CID},{XULRUNTIME_SERVICE_CONTRACTID,&kAPPINFO_CID},#ifdef MOZ_CRASHREPORTER{NS_CRASHREPORTER_CONTRACTID,&kAPPINFO_CID},#endif // MOZ_CRASHREPORTER{NS_PROFILESERVICE_CONTRACTID,&kProfileServiceCID},{nullptr}};staticconstmozilla::ModulekXREModule={mozilla::Module::kVersion,kXRECIDs,kXREContracts};NSMODULE_DEFN(Apprunner)=&kXREModule;nsresultScopedXPCOMStartup::Initialize(){NS_ASSERTION(gDirServiceProvider,"Should not get here!");nsresultrv;rv=NS_InitXPCOM2(&mServiceManager,gDirServiceProvider->GetAppDir(),gDirServiceProvider);if(NS_FAILED(rv)){NS_ERROR("Couldn't start xpcom!");mServiceManager=nullptr;}else{#ifdef DEBUGnsCOMPtr<nsIComponentRegistrar>reg=do_QueryInterface(mServiceManager);NS_ASSERTION(reg,"Service Manager doesn't QI to Registrar.");#endif}returnrv;}/** * This is a little factory class that serves as a singleton-service-factory * for the nativeappsupport object. */classnsSingletonFactoryfinal:publicnsIFactory{public:NS_DECL_ISUPPORTSNS_DECL_NSIFACTORYexplicitnsSingletonFactory(nsISupports*aSingleton);private:~nsSingletonFactory(){}nsCOMPtr<nsISupports>mSingleton;};nsSingletonFactory::nsSingletonFactory(nsISupports*aSingleton):mSingleton(aSingleton){NS_ASSERTION(mSingleton,"Singleton was null!");}NS_IMPL_ISUPPORTS(nsSingletonFactory,nsIFactory)NS_IMETHODIMPnsSingletonFactory::CreateInstance(nsISupports*aOuter,constnsIID&aIID,void**aResult){NS_ENSURE_NO_AGGREGATION(aOuter);returnmSingleton->QueryInterface(aIID,aResult);}NS_IMETHODIMPnsSingletonFactory::LockFactory(bool){returnNS_OK;}/** * Set our windowcreator on the WindowWatcher service. */nsresultScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport*native){nsresultrv;NS_IF_ADDREF(gNativeAppSupport=native);// Inform the chrome registry about OS accessibilitynsCOMPtr<nsIToolkitChromeRegistry>cr=mozilla::services::GetToolkitChromeRegistryService();if(cr)cr->CheckForOSAccessibility();nsCOMPtr<nsIWindowCreator>creator(components::AppStartup::Service());if(!creator)returnNS_ERROR_UNEXPECTED;nsCOMPtr<nsIWindowWatcher>wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID,&rv));NS_ENSURE_SUCCESS(rv,rv);returnwwatch->SetWindowCreator(creator);}/* static */already_AddRefed<nsINativeAppSupport>NS_GetNativeAppSupport(){if(!ScopedXPCOMStartup::gNativeAppSupport){returnnullptr;}returndo_AddRef(ScopedXPCOMStartup::gNativeAppSupport);}nsINativeAppSupport*ScopedXPCOMStartup::gNativeAppSupport;staticvoidDumpArbitraryHelp(){nsresultrv;ScopedLogginglog;{ScopedXPCOMStartupxpcom;xpcom.Initialize();nsCOMPtr<nsICommandLineRunner>cmdline(newnsCommandLine());nsCStringtext;rv=cmdline->GetHelpText(text);if(NS_SUCCEEDED(rv))printf("%s",text.get());}}// English text needs to go into a dtd file.// But when this is called we have no components etc. These strings must either// be here, or in a native resource file.staticvoidDumpHelp(){printf("Usage: %s [ options ... ] [URL]\n"" where options include:\n\n",gArgv[0]);#ifdef MOZ_X11printf("X11 options\n"" --display=DISPLAY X display to use\n"" --sync Make X calls synchronous\n");#endif#ifdef XP_UNIXprintf(" --g-fatal-warnings Make all warnings fatal\n""\n%s options\n",(constchar*)gAppData->name);#endifprintf(" -h or --help Print this message.\n"" -v or --version Print %s version.\n"" -P <profile> Start with <profile>.\n"" --profile <path> Start with profile at <path>.\n"" --migration Start with migration wizard.\n"" --ProfileManager Start with ProfileManager.\n"" --no-remote Do not accept or send remote commands; implies\n"" --new-instance.\n"" --new-instance Open new instance, not a new window in running ""instance.\n"" --UILocale <locale> Start with <locale> resources as UI Locale.\n"" --safe-mode Disables extensions and themes for this session.\n"#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE" --allow-downgrade Allows downgrading a profile.\n"#endif" -MOZ_LOG=<modules> Treated as MOZ_LOG=<modules> environment variable, ""overrides it.\n"" -MOZ_LOG_FILE=<file> Treated as MOZ_LOG_FILE=<file> environment ""variable, overrides it.\n"" If MOZ_LOG_FILE is not specified as an argument or ""as an environment variable,\n"" logging will be written to stdout.\n",(constchar*)gAppData->name);#if defined(XP_WIN)printf(" --console Start %s with a debugging console.\n",(constchar*)gAppData->name);#endif#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)printf(" --headless Run without a GUI.\n");#endifprintf(" --save-recordings Save recordings for all content processes to a ""directory.\n");// this works, but only after the components have registered. so if you drop// in a new command line handler, --help won't not until the second run. out// of the bug, because we ship a component.reg file, it works correctly.DumpArbitraryHelp();}staticinlinevoidDumpVersion(){if(gAppData->vendor){printf("%s ",(constchar*)gAppData->vendor);}printf("%s ",(constchar*)gAppData->name);// Use the displayed version// For example, for beta, we would display 42.0b2 instead of 42.0printf("%s",MOZ_APP_VERSION_DISPLAY);if(gAppData->copyright){printf(", %s",(constchar*)gAppData->copyright);}printf("\n");}#if defined(MOZ_WIDGET_GTK)staticRemoteResultParseRemoteCommandLine(nsCString&program,constchar**profile,constchar**username){ArgResultar;ar=CheckArg("p",profile,CheckArgFlag::None);if(ar==ARG_BAD){// Leave it to the normal command line handling to handle this situation.returnREMOTE_NOT_FOUND;}constchar*temp=nullptr;ar=CheckArg("a",&temp,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument -a requires an application name\n");returnREMOTE_ARG_BAD;}if(ar==ARG_FOUND){program.Assign(temp);}ar=CheckArg("u",username,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument -u requires a username\n");returnREMOTE_ARG_BAD;}returnREMOTE_FOUND;}staticRemoteResultStartRemoteClient(constchar*aDesktopStartupID,nsCString&program,constchar*profile,constchar*username){nsAutoPtr<nsRemoteClient>client;booluseX11Remote=GDK_IS_X11_DISPLAY(gdk_display_get_default());# if defined(MOZ_ENABLE_DBUS)if(!useX11Remote){client=newDBusRemoteClient();}# endifif(useX11Remote){client=newXRemoteClient();}nsresultrv=client?client->Init():NS_ERROR_FAILURE;if(NS_FAILED(rv))returnREMOTE_NOT_FOUND;nsCStringresponse;boolsuccess=false;rv=client->SendCommandLine(program.get(),username,profile,gArgc,gArgv,aDesktopStartupID,getter_Copies(response),&success);// did the command fail?if(!success)returnREMOTE_NOT_FOUND;// The "command not parseable" error is returned when the// nsICommandLineHandler throws a NS_ERROR_ABORT.if(response.EqualsLiteral("500 command not parseable"))returnREMOTE_ARG_BAD;if(NS_FAILED(rv))returnREMOTE_NOT_FOUND;returnREMOTE_FOUND;}#endif // MOZ_WIDGET_GTKvoidXRE_InitOmnijar(nsIFile*greOmni,nsIFile*appOmni){mozilla::Omnijar::Init(greOmni,appOmni);}nsresultXRE_GetBinaryPath(nsIFile**aResult){returnmozilla::BinaryPath::GetFile(aResult);}#ifdef XP_WIN# include "nsWindowsRestart.cpp"# include <shellapi.h>typedefBOOL(WINAPI*SetProcessDEPPolicyFunc)(DWORDdwFlags);staticvoidRegisterApplicationRestartChanged(constchar*aPref,void*aData){DWORDcchCmdLine=0;HRESULTrc=::GetApplicationRestartSettings(::GetCurrentProcess(),nullptr,&cchCmdLine,nullptr);boolwasRegistered=false;if(rc==S_OK){wasRegistered=true;}if(Preferences::GetBool(PREF_WIN_REGISTER_APPLICATION_RESTART,false)&&!wasRegistered){// Make the command line to use when restarting.// Excludes argv[0] because RegisterApplicationRestart adds the// executable name, replace that temporarily with -os-restartedchar*exeName=gRestartArgv[0];gRestartArgv[0]=const_cast<char*>("-os-restarted");wchar_t**restartArgvConverted=AllocConvertUTF8toUTF16Strings(gRestartArgc,gRestartArgv);gRestartArgv[0]=exeName;mozilla::UniquePtr<wchar_t[]>restartCommandLine;if(restartArgvConverted){restartCommandLine=mozilla::MakeCommandLine(gRestartArgc,restartArgvConverted);FreeAllocStrings(gRestartArgc,restartArgvConverted);}if(restartCommandLine){// Flags RESTART_NO_PATCH and RESTART_NO_REBOOT are not set, so we// should be restarted if terminated by an update or restart.::RegisterApplicationRestart(restartCommandLine.get(),RESTART_NO_CRASH|RESTART_NO_HANG);}}elseif(wasRegistered){::UnregisterApplicationRestart();}}# if defined(MOZ_LAUNCHER_PROCESS)staticvoidOnLauncherPrefChanged(constchar*aPref,void*aData){boolprefVal=Preferences::GetBool(PREF_WIN_LAUNCHER_PROCESS_ENABLED,false);mozilla::LauncherRegistryInfolauncherRegInfo;mozilla::LauncherVoidResultreflectResult=launcherRegInfo.ReflectPrefToRegistry(prefVal);MOZ_ASSERT(reflectResult.isOk());}staticvoidSetupLauncherProcessPref(){mozilla::LauncherRegistryInfolauncherRegInfo;mozilla::LauncherResult<mozilla::LauncherRegistryInfo::EnabledState>enabledState=launcherRegInfo.IsEnabled();if(enabledState.isOk()){Preferences::SetBool(PREF_WIN_LAUNCHER_PROCESS_ENABLED,enabledState.unwrap()!=mozilla::LauncherRegistryInfo::EnabledState::ForceDisabled);CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::LauncherProcessState,static_cast<uint32_t>(enabledState.unwrap()));}Preferences::RegisterCallback(&OnLauncherPrefChanged,PREF_WIN_LAUNCHER_PROCESS_ENABLED);}# endif // defined(MOZ_LAUNCHER_PROCESS)#endif // XP_WIN// If aBlankCommandLine is true, then the application will be launched with a// blank command line instead of being launched with the same command line that// it was initially started with.staticnsresultLaunchChild(nsINativeAppSupport*aNative,boolaBlankCommandLine=false){aNative->Quit();// release DDE mutex, if we're holding it// Restart this process by exec'ing it into the current process// if supported by the platform. Otherwise, use NSPR.#ifdef MOZ_JPROF// make sure JPROF doesn't think we're E10sunsetenv("JPROF_SLAVE");#endifif(aBlankCommandLine){gRestartArgc=1;gRestartArgv[gRestartArgc]=nullptr;}SaveToEnv("MOZ_LAUNCHED_CHILD=1");#if defined(MOZ_LAUNCHER_PROCESS)SaveToEnv("MOZ_LAUNCHER_PROCESS=1");#endif // defined(MOZ_LAUNCHER_PROCESS)#if !defined(MOZ_WIDGET_ANDROID) // Android has separate restart code.# if defined(XP_MACOSX)CommandLineServiceMac::SetupMacCommandLine(gRestartArgc,gRestartArgv,true);LaunchChildMac(gRestartArgc,gRestartArgv);# elsensCOMPtr<nsIFile>lf;nsresultrv=XRE_GetBinaryPath(getter_AddRefs(lf));if(NS_FAILED(rv))returnrv;# if defined(XP_WIN)nsAutoStringexePath;rv=lf->GetPath(exePath);if(NS_FAILED(rv))returnrv;HANDLEhProcess;if(!WinLaunchChild(exePath.get(),gRestartArgc,gRestartArgv,nullptr,&hProcess))returnNS_ERROR_FAILURE;// Keep the current process around until the restarted process has created// its message queue, to avoid the launched process's windows being forced// into the background.mozilla::WaitForInputIdle(hProcess);::CloseHandle(hProcess);# elsensAutoCStringexePath;rv=lf->GetNativePath(exePath);if(NS_FAILED(rv))returnrv;# if defined(XP_UNIX)if(execv(exePath.get(),gRestartArgv)==-1)returnNS_ERROR_FAILURE;# elsePRProcess*process=PR_CreateProcess(exePath.get(),gRestartArgv,nullptr,nullptr);if(!process)returnNS_ERROR_FAILURE;int32_texitCode;PRStatusfailed=PR_WaitProcess(process,&exitCode);if(failed||exitCode)returnNS_ERROR_FAILURE;# endif // XP_UNIX# endif // WP_WIN# endif // WP_MACOSX#endif // MOZ_WIDGET_ANDROIDreturnNS_ERROR_LAUNCHED_CHILD_PROCESS;}staticconstcharkProfileProperties[]="chrome://mozapps/locale/profile/profileSelection.properties";namespace{/** * This class, instead of a raw nsresult, should be the return type of any * function called by SelectProfile that initializes XPCOM. */classReturnAbortOnError{public:MOZ_IMPLICITReturnAbortOnError(nsresultaRv){mRv=ConvertRv(aRv);}operatornsresult(){returnmRv;}private:inlinensresultConvertRv(nsresultaRv){if(NS_SUCCEEDED(aRv)||aRv==NS_ERROR_LAUNCHED_CHILD_PROCESS){returnaRv;}returnNS_ERROR_ABORT;}nsresultmRv;};}// namespacestaticnsresultProfileMissingDialog(nsINativeAppSupport*aNative){nsresultrv;ScopedXPCOMStartupxpcom;rv=xpcom.Initialize();NS_ENSURE_SUCCESS(rv,rv);rv=xpcom.SetWindowCreator(aNative);NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);{// extra scoping is needed so we release these components before xpcom// shutdownnsCOMPtr<nsIStringBundleService>sbs=mozilla::services::GetStringBundleService();NS_ENSURE_TRUE(sbs,NS_ERROR_FAILURE);nsCOMPtr<nsIStringBundle>sb;sbs->CreateBundle(kProfileProperties,getter_AddRefs(sb));NS_ENSURE_TRUE_LOG(sbs,NS_ERROR_FAILURE);NS_ConvertUTF8toUTF16appName(gAppData->name);constchar16_t*params[]={appName.get(),appName.get()};// profileMissingnsAutoStringmissingMessage;rv=sb->FormatStringFromName("profileMissing",params,2,missingMessage);NS_ENSURE_SUCCESS(rv,NS_ERROR_ABORT);nsAutoStringmissingTitle;rv=sb->FormatStringFromName("profileMissingTitle",params,1,missingTitle);NS_ENSURE_SUCCESS(rv,NS_ERROR_ABORT);nsCOMPtr<nsIPromptService>ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID));NS_ENSURE_TRUE(ps,NS_ERROR_FAILURE);ps->Alert(nullptr,missingTitle.get(),missingMessage.get());returnNS_ERROR_ABORT;}}staticReturnAbortOnErrorProfileLockedDialog(nsIFile*aProfileDir,nsIFile*aProfileLocalDir,nsIProfileUnlocker*aUnlocker,nsINativeAppSupport*aNative,nsIProfileLock**aResult){nsresultrv;boolexists;aProfileDir->Exists(&exists);if(!exists){returnProfileMissingDialog(aNative);}ScopedXPCOMStartupxpcom;rv=xpcom.Initialize();NS_ENSURE_SUCCESS(rv,rv);mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);rv=xpcom.SetWindowCreator(aNative);NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);{// extra scoping is needed so we release these components before xpcom// shutdownnsCOMPtr<nsIStringBundleService>sbs=mozilla::services::GetStringBundleService();NS_ENSURE_TRUE(sbs,NS_ERROR_FAILURE);nsCOMPtr<nsIStringBundle>sb;sbs->CreateBundle(kProfileProperties,getter_AddRefs(sb));NS_ENSURE_TRUE_LOG(sbs,NS_ERROR_FAILURE);NS_ConvertUTF8toUTF16appName(gAppData->name);constchar16_t*params[]={appName.get(),appName.get()};nsAutoStringkillMessage;#ifndef XP_MACOSXrv=sb->FormatStringFromName(aUnlocker?"restartMessageUnlocker":"restartMessageNoUnlocker",params,2,killMessage);#elserv=sb->FormatStringFromName(aUnlocker?"restartMessageUnlockerMac":"restartMessageNoUnlockerMac",params,2,killMessage);#endifNS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);nsAutoStringkillTitle;rv=sb->FormatStringFromName("restartTitle",params,1,killTitle);NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);if(gfxPlatform::IsHeadless()){// TODO: make a way to turn off all dialogs when headless.Output(true,"%s\n",NS_LossyConvertUTF16toASCII(killMessage).get());returnNS_ERROR_FAILURE;}nsCOMPtr<nsIPromptService>ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID));NS_ENSURE_TRUE(ps,NS_ERROR_FAILURE);if(aUnlocker){int32_tbutton;#ifdef MOZ_WIDGET_ANDROIDjava::GeckoAppShell::KillAnyZombies();button=0;#elseconstuint32_tflags=(nsIPromptService::BUTTON_TITLE_IS_STRING*nsIPromptService::BUTTON_POS_0)+(nsIPromptService::BUTTON_TITLE_CANCEL*nsIPromptService::BUTTON_POS_1);boolcheckState=false;rv=ps->ConfirmEx(nullptr,killTitle.get(),killMessage.get(),flags,killTitle.get(),nullptr,nullptr,nullptr,&checkState,&button);NS_ENSURE_SUCCESS_LOG(rv,rv);#endifif(button==0){rv=aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);if(NS_FAILED(rv)){returnrv;}SaveFileToEnv("XRE_PROFILE_PATH",aProfileDir);SaveFileToEnv("XRE_PROFILE_LOCAL_PATH",aProfileLocalDir);returnLaunchChild(aNative);}}else{#ifdef MOZ_WIDGET_ANDROIDif(java::GeckoAppShell::UnlockProfile()){returnNS_LockProfilePath(aProfileDir,aProfileLocalDir,nullptr,aResult);}#elserv=ps->Alert(nullptr,killTitle.get(),killMessage.get());NS_ENSURE_SUCCESS_LOG(rv,rv);#endif}returnNS_ERROR_ABORT;}}staticnsresultProfileLockedDialog(nsIToolkitProfile*aProfile,nsIProfileUnlocker*aUnlocker,nsINativeAppSupport*aNative,nsIProfileLock**aResult){nsCOMPtr<nsIFile>profileDir;nsresultrv=aProfile->GetRootDir(getter_AddRefs(profileDir));if(NS_FAILED(rv))returnrv;nsCOMPtr<nsIFile>profileLocalDir;rv=aProfile->GetLocalDir(getter_AddRefs(profileLocalDir));if(NS_FAILED(rv))returnrv;returnProfileLockedDialog(profileDir,profileLocalDir,aUnlocker,aNative,aResult);}staticconstcharkProfileManagerURL[]="chrome://mozapps/content/profile/profileSelection.xul";staticReturnAbortOnErrorShowProfileManager(nsIToolkitProfileService*aProfileSvc,nsINativeAppSupport*aNative){nsresultrv;nsCOMPtr<nsIFile>profD,profLD;booloffline=false;{ScopedXPCOMStartupxpcom;rv=xpcom.Initialize();NS_ENSURE_SUCCESS(rv,rv);// Initialize the graphics prefs, some of the paths need them before// any other graphics is initialized (e.g., showing the profile chooser.)gfxPrefs::GetSingleton();rv=xpcom.SetWindowCreator(aNative);NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);#ifdef XP_MACOSXCommandLineServiceMac::SetupMacCommandLine(gRestartArgc,gRestartArgv,true);#endif#ifdef XP_WIN// we don't have to wait here because profile manager window will pump// and DDE message will be handledProcessDDE(aNative,false);#endif{// extra scoping is needed so we release these components before xpcom// shutdownnsCOMPtr<nsIWindowWatcher>windowWatcher(do_GetService(NS_WINDOWWATCHER_CONTRACTID));nsCOMPtr<nsIDialogParamBlock>ioParamBlock(do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID));nsCOMPtr<nsIMutableArray>dlgArray(do_CreateInstance(NS_ARRAY_CONTRACTID));NS_ENSURE_TRUE(windowWatcher&&ioParamBlock&&dlgArray,NS_ERROR_FAILURE);ioParamBlock->SetObjects(dlgArray);nsCOMPtr<nsIAppStartup>appStartup(components::AppStartup::Service());NS_ENSURE_TRUE(appStartup,NS_ERROR_FAILURE);nsCOMPtr<mozIDOMWindowProxy>newWindow;rv=windowWatcher->OpenWindow(nullptr,kProfileManagerURL,"_blank","centerscreen,chrome,modal,titlebar",ioParamBlock,getter_AddRefs(newWindow));NS_ENSURE_SUCCESS_LOG(rv,rv);aProfileSvc->Flush();int32_tdialogConfirmed;rv=ioParamBlock->GetInt(0,&dialogConfirmed);if(NS_FAILED(rv)||dialogConfirmed==0)returnNS_ERROR_ABORT;int32_tstartOffline;rv=ioParamBlock->GetInt(1,&startOffline);offline=NS_SUCCEEDED(rv)&&startOffline==1;nsCOMPtr<nsIProfileLock>lock;rv=dlgArray->QueryElementAt(0,NS_GET_IID(nsIProfileLock),getter_AddRefs(lock));NS_ENSURE_SUCCESS_LOG(rv,rv);rv=lock->GetDirectory(getter_AddRefs(profD));NS_ENSURE_SUCCESS(rv,rv);rv=lock->GetLocalDirectory(getter_AddRefs(profLD));NS_ENSURE_SUCCESS(rv,rv);lock->Unlock();}}SaveFileToEnv("XRE_PROFILE_PATH",profD);SaveFileToEnv("XRE_PROFILE_LOCAL_PATH",profLD);SaveToEnv("XRE_RESTARTED_BY_PROFILE_MANAGER=1");if(offline){SaveToEnv("XRE_START_OFFLINE=1");}if(gRestartedByOS){// Re-add this argument when actually starting the application.char**newArgv=(char**)realloc(gRestartArgv,sizeof(char*)*(gRestartArgc+2));NS_ENSURE_TRUE(newArgv,NS_ERROR_OUT_OF_MEMORY);gRestartArgv=newArgv;gRestartArgv[gRestartArgc++]=const_cast<char*>("-os-restarted");gRestartArgv[gRestartArgc]=nullptr;}returnLaunchChild(aNative);}staticboolgDoMigration=false;staticboolgDoProfileReset=false;staticnsCOMPtr<nsIToolkitProfile>gResetOldProfile;// Pick a profile. We need to end up with a profile lock.//// 1) check for --profile <path>// 2) check for -P <name>// 3) check for --ProfileManager// 4) use the default profile, if there is one// 5) if there are *no* profiles, set up profile-migration// 6) display the profile-manager UIstaticnsresultSelectProfile(nsIProfileLock**aResult,nsIToolkitProfileService*aProfileSvc,nsINativeAppSupport*aNative,bool*aStartOffline,nsACString*aProfileName){StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);nsresultrv;ArgResultar;*aResult=nullptr;*aStartOffline=false;ar=CheckArg("offline",nullptr,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --offline is invalid when argument --osint is ""specified\n");returnNS_ERROR_FAILURE;}if(ar||EnvHasValue("XRE_START_OFFLINE"))*aStartOffline=true;if(EnvHasValue("MOZ_RESET_PROFILE_RESTART")){gDoProfileReset=true;gDoMigration=true;SaveToEnv("MOZ_RESET_PROFILE_RESTART=");// We only want to restore the previous session if the profile refresh was// triggered by user. And if it was a user-triggered profile refresh// through, say, the safeMode dialog or the troubleshooting page, the// MOZ_RESET_PROFILE_RESTART env variable would be set. Hence we set// MOZ_RESET_PROFILE_MIGRATE_SESSION here so that Firefox profile migrator// would migrate old session data later.SaveToEnv("MOZ_RESET_PROFILE_MIGRATE_SESSION=1");}// reset-profile and migration args need to be checked before any profiles are// chosen below.ar=CheckArg("reset-profile",nullptr,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --reset-profile is invalid when argument ""--osint is specified\n");returnNS_ERROR_FAILURE;}if(ar==ARG_FOUND){gDoProfileReset=true;}ar=CheckArg("migration",nullptr,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --migration is invalid when argument --osint ""is specified\n");returnNS_ERROR_FAILURE;}if(ar==ARG_FOUND){gDoMigration=true;}nsCOMPtr<nsIFile>rootDir;nsCOMPtr<nsIFile>localDir;nsCOMPtr<nsIToolkitProfile>profile;// Ask the profile manager to select the profile directories to use.nsToolkitProfileService*service=static_cast<nsToolkitProfileService*>(aProfileSvc);booldidCreate=false;rv=service->SelectStartupProfile(&gArgc,gArgv,gDoProfileReset,getter_AddRefs(rootDir),getter_AddRefs(localDir),getter_AddRefs(profile),&didCreate);if(rv==NS_ERROR_SHOW_PROFILE_MANAGER){returnShowProfileManager(aProfileSvc,aNative);}NS_ENSURE_SUCCESS(rv,rv);if(didCreate){// For a fresh install, we would like to let users decide// to do profile migration on their own later after using.gDoProfileReset=false;gDoMigration=false;}if(gDoProfileReset){if(!profile){NS_WARNING("Profile reset is only supported for named profiles.");returnNS_ERROR_ABORT;}{// Check that the source profile is not in use by temporarily// acquiring its lock.nsIProfileLock*tempProfileLock;nsCOMPtr<nsIProfileUnlocker>unlocker;rv=profile->Lock(getter_AddRefs(unlocker),&tempProfileLock);if(NS_FAILED(rv)){returnProfileLockedDialog(profile,unlocker,aNative,&tempProfileLock);}}// If we're resetting a profile, create a new one and use it to startup.gResetOldProfile=profile;rv=service->CreateResetProfile(getter_AddRefs(profile));if(NS_SUCCEEDED(rv)){rv=profile->GetRootDir(getter_AddRefs(rootDir));NS_ENSURE_SUCCESS(rv,rv);SaveFileToEnv("XRE_PROFILE_PATH",rootDir);rv=profile->GetLocalDir(getter_AddRefs(localDir));NS_ENSURE_SUCCESS(rv,rv);SaveFileToEnv("XRE_PROFILE_LOCAL_PATH",localDir);rv=profile->GetName(*aProfileName);if(NS_FAILED(rv)){aProfileName->Truncate(0);}}else{NS_WARNING("Profile reset failed.");returnNS_ERROR_ABORT;}}// No profile could be found. This generally shouldn't happen, a new profile// should be created in all cases except for profile reset which is covered// above, but just in case...if(!rootDir){returnNS_ERROR_ABORT;}// If you close Firefox and very quickly reopen it, the old Firefox may// still be closing down. Rather than immediately showing the// "Firefox is running but is not responding" message, we spend a few// seconds retrying first.staticconstintkLockRetrySeconds=5;staticconstintkLockRetrySleepMS=100;nsCOMPtr<nsIProfileUnlocker>unlocker;constTimeStampstart=TimeStamp::Now();do{if(profile){rv=profile->Lock(getter_AddRefs(unlocker),aResult);}else{rv=NS_LockProfilePath(rootDir,localDir,getter_AddRefs(unlocker),aResult);}if(NS_SUCCEEDED(rv)){StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);// Try to grab the profile name.if(aProfileName&&profile){rv=profile->GetName(*aProfileName);if(NS_FAILED(rv)){aProfileName->Truncate(0);}}returnNS_OK;}PR_Sleep(kLockRetrySleepMS);}while(TimeStamp::Now()-start<TimeDuration::FromSeconds(kLockRetrySeconds));returnProfileLockedDialog(rootDir,localDir,unlocker,aNative,aResult);}#ifdef MOZ_BLOCK_PROFILE_DOWNGRADEstructFileWriteFunc:publicJSONWriteFunc{FILE*mFile;explicitFileWriteFunc(FILE*aFile):mFile(aFile){}voidWrite(constchar*aStr)override{fprintf(mFile,"%s",aStr);}};staticvoidSubmitDowngradeTelemetry(constnsCString&aLastVersion,boolaHasSync,int32_taButton){nsCOMPtr<nsIPrefService>prefSvc=do_GetService("@mozilla.org/preferences-service;1");NS_ENSURE_TRUE_VOID(prefSvc);nsCOMPtr<nsIPrefBranch>prefBranch=do_QueryInterface(prefSvc);NS_ENSURE_TRUE_VOID(prefBranch);boolenabled;nsresultrv=prefBranch->GetBoolPref("datareporting.healthreport.uploadEnabled",&enabled);NS_ENSURE_SUCCESS_VOID(rv);if(!enabled){return;}nsCStringserver;rv=prefBranch->GetCharPref("toolkit.telemetry.server",server);NS_ENSURE_SUCCESS_VOID(rv);nsCStringclientId;rv=prefBranch->GetCharPref("toolkit.telemetry.cachedClientID",clientId);NS_ENSURE_SUCCESS_VOID(rv);rv=prefSvc->GetDefaultBranch(nullptr,getter_AddRefs(prefBranch));NS_ENSURE_SUCCESS_VOID(rv);nsCStringchannel("default");rv=prefBranch->GetCharPref("app.update.channel",channel);NS_ENSURE_SUCCESS_VOID(rv);nsIDuuid;nsCOMPtr<nsIUUIDGenerator>uuidGen=do_GetService("@mozilla.org/uuid-generator;1");NS_ENSURE_TRUE_VOID(uuidGen);rv=uuidGen->GenerateUUIDInPlace(&uuid);NS_ENSURE_SUCCESS_VOID(rv);charstrid[NSID_LENGTH];uuid.ToProvidedString(strid);nsCStringarch("null");nsCOMPtr<nsIPropertyBag2>sysInfo=do_GetService("@mozilla.org/system-info;1");NS_ENSURE_TRUE_VOID(sysInfo);sysInfo->GetPropertyAsACString(NS_LITERAL_STRING("arch"),arch);time_tnow;time(&now);chardate[sizeof"YYYY-MM-DDThh:mm:ss.000Z"];strftime(date,sizeofdate,"%FT%T.000Z",gmtime(&now));// NSID_LENGTH includes the trailing \0 and we also want to strip off the// surrounding braces so the length becomes NSID_LENGTH - 3.nsDependentCSubstringpingId(strid+1,NSID_LENGTH-3);NS_NAMED_LITERAL_CSTRING(pingType,"downgrade");int32_tpos=aLastVersion.Find("_");if(pos==kNotFound){return;}constnsDependentCSubstringlastVersion=Substring(aLastVersion,0,pos);constnsDependentCSubstringlastBuildId=Substring(aLastVersion,pos+1,14);nsPrintfCStringurl("%s/submit/telemetry/%s/%s/%s/%s/%s/%s?v=%d",server.get(),PromiseFlatCString(pingId).get(),pingType.get(),(constchar*)gAppData->name,(constchar*)gAppData->version,channel.get(),(constchar*)gAppData->buildID,TELEMETRY_PING_FORMAT_VERSION);nsCOMPtr<nsIFile>pingFile;rv=NS_GetSpecialDirectory(XRE_USER_APP_DATA_DIR,getter_AddRefs(pingFile));NS_ENSURE_SUCCESS_VOID(rv);rv=pingFile->Append(NS_LITERAL_STRING("Pending Pings"));NS_ENSURE_SUCCESS_VOID(rv);rv=pingFile->Create(nsIFile::DIRECTORY_TYPE,0755);if(NS_FAILED(rv)&&rv!=NS_ERROR_FILE_ALREADY_EXISTS){return;}rv=pingFile->Append(NS_ConvertUTF8toUTF16(pingId));NS_ENSURE_SUCCESS_VOID(rv);nsCOMPtr<nsIFile>pingSender;rv=NS_GetSpecialDirectory(NS_GRE_BIN_DIR,getter_AddRefs(pingSender));NS_ENSURE_SUCCESS_VOID(rv);# ifdef XP_WINpingSender->Append(NS_LITERAL_STRING("pingsender.exe"));# elsepingSender->Append(NS_LITERAL_STRING("pingsender"));# endifboolexists;rv=pingSender->Exists(&exists);NS_ENSURE_SUCCESS_VOID(rv);if(!exists){return;}FILE*file;rv=pingFile->OpenANSIFileDesc("w",&file);NS_ENSURE_SUCCESS_VOID(rv);JSONWriterw(MakeUnique<FileWriteFunc>(file));w.Start();{w.StringProperty("type",pingType.get());w.StringProperty("id",PromiseFlatCString(pingId).get());w.StringProperty("creationDate",date);w.IntProperty("version",TELEMETRY_PING_FORMAT_VERSION);w.StringProperty("clientId",clientId.get());w.StartObjectProperty("application");{w.StringProperty("architecture",arch.get());w.StringProperty("buildId",gAppData->buildID);w.StringProperty("name",gAppData->name);w.StringProperty("version",gAppData->version);w.StringProperty("displayVersion",NS_STRINGIFY(MOZ_APP_VERSION_DISPLAY));w.StringProperty("vendor",gAppData->vendor);w.StringProperty("platformVersion",gToolkitVersion);# ifdef TARGET_XPCOM_ABIw.StringProperty("xpcomAbi",TARGET_XPCOM_ABI);# elsew.StringProperty("xpcomAbi","unknown");# endifw.StringProperty("channel",channel.get());}w.EndObject();w.StartObjectProperty("payload");{w.StringProperty("lastVersion",PromiseFlatCString(lastVersion).get());w.StringProperty("lastBuildId",PromiseFlatCString(lastBuildId).get());w.BoolProperty("hasSync",aHasSync);w.IntProperty("button",aButton);}w.EndObject();}w.End();fclose(file);PathStringfilePath=pingFile->NativePath();constfilesystem::Path::value_type*args[2];# ifdef XP_WINnsStringurlw=NS_ConvertUTF8toUTF16(url);args[0]=urlw.get();# elseargs[0]=url.get();# endifargs[1]=filePath.get();nsCOMPtr<nsIProcess>process=do_CreateInstance("@mozilla.org/process/util;1");NS_ENSURE_TRUE_VOID(process);process->Init(pingSender);process->SetStartHidden(true);process->SetNoShell(true);# ifdef XP_WINprocess->Runw(false,args,2);# elseprocess->Run(false,args,2);# endif}staticconstcharkProfileDowngradeURL[]="chrome://mozapps/content/profile/profileDowngrade.xul";staticReturnAbortOnErrorCheckDowngrade(nsIFile*aProfileDir,nsIFile*aProfileLocalDir,nsACString&aProfileName,nsINativeAppSupport*aNative,nsIToolkitProfileService*aProfileSvc,constnsCString&aLastVersion){int32_tresult=0;nsresultrv;{if(gfxPlatform::IsHeadless()){// TODO: make a way to turn off all dialogs when headless.Output(true,"This profile was last used with a newer version of this ""application. Please create a new profile.\n");returnNS_ERROR_ABORT;}ScopedXPCOMStartupxpcom;rv=xpcom.Initialize();NS_ENSURE_SUCCESS(rv,rv);rv=xpcom.SetWindowCreator(aNative);NS_ENSURE_SUCCESS(rv,rv);{// extra scoping is needed so we release these components before xpcom// shutdownboolhasSync=false;nsCOMPtr<nsIPrefService>prefSvc=do_GetService("@mozilla.org/preferences-service;1");NS_ENSURE_TRUE(prefSvc,rv);nsCOMPtr<nsIFile>prefsFile;rv=aProfileDir->Clone(getter_AddRefs(prefsFile));NS_ENSURE_SUCCESS(rv,rv);rv=prefsFile->Append(NS_LITERAL_STRING("prefs.js"));NS_ENSURE_SUCCESS(rv,rv);rv=prefSvc->ReadUserPrefsFromFile(prefsFile);if(NS_SUCCEEDED(rv)){nsCOMPtr<nsIPrefBranch>prefBranch=do_QueryInterface(prefSvc);rv=prefBranch->PrefHasUserValue("services.sync.username",&hasSync);NS_ENSURE_SUCCESS(rv,rv);}nsCOMPtr<nsIWindowWatcher>windowWatcher=do_GetService(NS_WINDOWWATCHER_CONTRACTID);NS_ENSURE_TRUE(windowWatcher,NS_ERROR_ABORT);nsCOMPtr<nsIAppStartup>appStartup(components::AppStartup::Service());NS_ENSURE_TRUE(appStartup,NS_ERROR_FAILURE);nsCOMPtr<nsIDialogParamBlock>paramBlock=do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID);NS_ENSURE_TRUE(paramBlock,NS_ERROR_ABORT);uint8_tflags=0;if(hasSync){flags|=nsIToolkitProfileService::hasSync;}paramBlock->SetInt(0,flags);nsCOMPtr<mozIDOMWindowProxy>newWindow;rv=windowWatcher->OpenWindow(nullptr,kProfileDowngradeURL,"_blank","centerscreen,chrome,modal,titlebar",paramBlock,getter_AddRefs(newWindow));NS_ENSURE_SUCCESS(rv,rv);paramBlock->GetInt(1,&result);SubmitDowngradeTelemetry(aLastVersion,hasSync,result);}}if(result==nsIToolkitProfileService::createNewProfile){// Create a new profile and start it.nsCStringprofileName;profileName.AssignLiteral("default");# ifdef MOZ_DEDICATED_PROFILESprofileName.Append("-"NS_STRINGIFY(MOZ_UPDATE_CHANNEL));# endifnsCOMPtr<nsIToolkitProfile>newProfile;rv=aProfileSvc->CreateUniqueProfile(nullptr,profileName,getter_AddRefs(newProfile));NS_ENSURE_SUCCESS(rv,rv);rv=aProfileSvc->SetDefaultProfile(newProfile);NS_ENSURE_SUCCESS(rv,rv);rv=aProfileSvc->Flush();NS_ENSURE_SUCCESS(rv,rv);nsCOMPtr<nsIFile>profD,profLD;rv=newProfile->GetRootDir(getter_AddRefs(profD));NS_ENSURE_SUCCESS(rv,rv);rv=newProfile->GetLocalDir(getter_AddRefs(profLD));NS_ENSURE_SUCCESS(rv,rv);SaveFileToEnv("XRE_PROFILE_PATH",profD);SaveFileToEnv("XRE_PROFILE_LOCAL_PATH",profLD);returnLaunchChild(aNative);}// CancelreturnNS_ERROR_ABORT;}#endif/** * The version string used in compatibility.ini is in the form * <appversion>_<appbuildid>/<aplatformbuildidid>. The build IDs are in the form * <year><month><day><hour><minute><second>. We need to be able to turn this * into something that can be compared by the version comparator. Build IDs are * numeric so normally we could just use those as part of the version but they * are larger than 32-bit integers so we must split them into two parts. * So we generate a version string of the format: * <appversion>.<appbuilddate>.<appbuildtime>.<platformbuilddate>.<platformbuildtime> * This doesn't compare correctly so * we have to make the build ids separate version parts instead. We also have * to split up the build ids as they are too large for the version comparator's * brain. */// Build ID dates are 8 digits, build ID times are 6 digits.#define BUILDID_DATE_LENGTH 8#define BUILDID_TIME_LENGTH 6#define BUILDID_LENGTH BUILDID_DATE_LENGTH + BUILDID_TIME_LENGTHstaticvoidGetBuildIDVersions(constnsACString&aFullVersion,int32_taPos,nsACString&aBuildVersions){// Extract the date part then the time part.aBuildVersions.Assign(Substring(aFullVersion,aPos,BUILDID_DATE_LENGTH)+NS_LITERAL_CSTRING(".")+Substring(aFullVersion,aPos+BUILDID_DATE_LENGTH,BUILDID_TIME_LENGTH));}staticVersionGetComparableVersion(constnsCString&aVersionStr){// We'll find the position of the '_' and '/' characters. The length from the// '_' character to the '/' character will be the length of a build ID plus// one for the '_' character. Similarly the length from the '/' character to// the end of the string will be the same.constuint32_tkExpectedLength=BUILDID_LENGTH+1;int32_tunderscorePos=aVersionStr.FindChar('_');int32_tslashPos=aVersionStr.FindChar('/');if(underscorePos==kNotFound||slashPos==kNotFound||(slashPos-underscorePos)!=kExpectedLength||(aVersionStr.Length()-slashPos)!=kExpectedLength){NS_WARNING("compatibility.ini Version string does not match the expected format.");returnVersion(aVersionStr.get());}nsCStringappBuild,platBuild;NS_NAMED_LITERAL_CSTRING(dot,".");constnsACString&version=Substring(aVersionStr,0,underscorePos);GetBuildIDVersions(aVersionStr,underscorePos+1,/* outparam */appBuild);GetBuildIDVersions(aVersionStr,slashPos+1,/* outparam */platBuild);constnsACString&fullVersion=version+dot+appBuild+dot+platBuild;returnVersion(PromiseFlatCString(fullVersion).get());}/** * Checks the compatibility.ini file to see if we have updated our application * or otherwise invalidated our caches. If the application has been updated, * we return false; otherwise, we return true. We also write the status * of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK * is always invalid if the application has been updated. aIsDowngrade is set to * true if the current application is older than that previously used by the * profile. */staticboolCheckCompatibility(nsIFile*aProfileDir,constnsCString&aVersion,constnsCString&aOSABI,nsIFile*aXULRunnerDir,nsIFile*aAppDir,nsIFile*aFlagFile,bool*aCachesOK,bool*aIsDowngrade,nsCString&aLastVersion){*aCachesOK=false;*aIsDowngrade=false;nsCOMPtr<nsIFile>file;aProfileDir->Clone(getter_AddRefs(file));if(!file)returnfalse;file->AppendNative(FILE_COMPATIBILITY_INFO);nsINIParserparser;nsresultrv=parser.Init(file);if(NS_FAILED(rv))returnfalse;rv=parser.GetString("Compatibility","LastVersion",aLastVersion);if(NS_FAILED(rv)){returnfalse;}if(!aVersion.Equals(aLastVersion)){Versioncurrent=GetComparableVersion(aVersion);Versionlast=GetComparableVersion(aLastVersion);*aIsDowngrade=last>current;returnfalse;}nsAutoCStringbuf;rv=parser.GetString("Compatibility","LastOSABI",buf);if(NS_FAILED(rv)||!aOSABI.Equals(buf))returnfalse;rv=parser.GetString("Compatibility","LastPlatformDir",buf);if(NS_FAILED(rv))returnfalse;nsCOMPtr<nsIFile>lf;rv=NS_NewNativeLocalFile(EmptyCString(),false,getter_AddRefs(lf));if(NS_FAILED(rv))returnfalse;rv=lf->SetPersistentDescriptor(buf);if(NS_FAILED(rv))returnfalse;booleq;rv=lf->Equals(aXULRunnerDir,&eq);if(NS_FAILED(rv)||!eq)returnfalse;if(aAppDir){rv=parser.GetString("Compatibility","LastAppDir",buf);if(NS_FAILED(rv))returnfalse;rv=NS_NewNativeLocalFile(EmptyCString(),false,getter_AddRefs(lf));if(NS_FAILED(rv))returnfalse;rv=lf->SetPersistentDescriptor(buf);if(NS_FAILED(rv))returnfalse;rv=lf->Equals(aAppDir,&eq);if(NS_FAILED(rv)||!eq)returnfalse;}// If we see this flag, caches are invalid.rv=parser.GetString("Compatibility","InvalidateCaches",buf);*aCachesOK=(NS_FAILED(rv)||!buf.EqualsLiteral("1"));boolpurgeCaches=false;if(aFlagFile){aFlagFile->Exists(&purgeCaches);}*aCachesOK=!purgeCaches&&*aCachesOK;returntrue;}staticvoidBuildVersion(nsCString&aBuf){aBuf.Assign(gAppData->version);aBuf.Append('_');aBuf.Append(gAppData->buildID);aBuf.Append('/');aBuf.Append(gToolkitBuildID);}staticvoidWriteVersion(nsIFile*aProfileDir,constnsCString&aVersion,constnsCString&aOSABI,nsIFile*aXULRunnerDir,nsIFile*aAppDir,boolinvalidateCache){nsCOMPtr<nsIFile>file;aProfileDir->Clone(getter_AddRefs(file));if(!file)return;file->AppendNative(FILE_COMPATIBILITY_INFO);nsAutoCStringplatformDir;Unused<<aXULRunnerDir->GetPersistentDescriptor(platformDir);nsAutoCStringappDir;if(aAppDir)Unused<<aAppDir->GetPersistentDescriptor(appDir);PRFileDesc*fd;nsresultrv=file->OpenNSPRFileDesc(PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,0600,&fd);if(NS_FAILED(rv)){NS_ERROR("could not create output stream");return;}staticconstcharkHeader[]="[Compatibility]"NS_LINEBREAK"LastVersion=";PR_Write(fd,kHeader,sizeof(kHeader)-1);PR_Write(fd,aVersion.get(),aVersion.Length());staticconstcharkOSABIHeader[]=NS_LINEBREAK"LastOSABI=";PR_Write(fd,kOSABIHeader,sizeof(kOSABIHeader)-1);PR_Write(fd,aOSABI.get(),aOSABI.Length());staticconstcharkPlatformDirHeader[]=NS_LINEBREAK"LastPlatformDir=";PR_Write(fd,kPlatformDirHeader,sizeof(kPlatformDirHeader)-1);PR_Write(fd,platformDir.get(),platformDir.Length());staticconstcharkAppDirHeader[]=NS_LINEBREAK"LastAppDir=";if(aAppDir){PR_Write(fd,kAppDirHeader,sizeof(kAppDirHeader)-1);PR_Write(fd,appDir.get(),appDir.Length());}staticconstcharkInvalidationHeader[]=NS_LINEBREAK"InvalidateCaches=1";if(invalidateCache)PR_Write(fd,kInvalidationHeader,sizeof(kInvalidationHeader)-1);staticconstcharkNL[]=NS_LINEBREAK;PR_Write(fd,kNL,sizeof(kNL)-1);PR_Close(fd);}/** * Returns true if the startup cache file was successfully removed. * Returns false if file->Clone fails at any point (OOM) or if unable * to remove the startup cache file. Note in particular the return value * is unaffected by a failure to remove extensions.ini */staticboolRemoveComponentRegistries(nsIFile*aProfileDir,nsIFile*aLocalProfileDir,boolaRemoveEMFiles){nsCOMPtr<nsIFile>file;aProfileDir->Clone(getter_AddRefs(file));if(!file)returnfalse;if(aRemoveEMFiles){file->SetNativeLeafName(NS_LITERAL_CSTRING("extensions.ini"));file->Remove(false);}aLocalProfileDir->Clone(getter_AddRefs(file));if(!file)returnfalse;#if defined(XP_UNIX) || defined(XP_BEOS)# define PLATFORM_FASL_SUFFIX ".mfasl"#elif defined(XP_WIN)# define PLATFORM_FASL_SUFFIX ".mfl"#endiffile->AppendNative(NS_LITERAL_CSTRING("XUL"PLATFORM_FASL_SUFFIX));file->Remove(false);file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC"PLATFORM_FASL_SUFFIX));file->Remove(false);file->SetNativeLeafName(NS_LITERAL_CSTRING("startupCache"));nsresultrv=file->Remove(true);returnNS_SUCCEEDED(rv)||rv==NS_ERROR_FILE_TARGET_DOES_NOT_EXIST||rv==NS_ERROR_FILE_NOT_FOUND;}// To support application initiated restart via nsIAppStartup.quit, we// need to save various environment variables, and then restore them// before re-launching the application.staticstructSavedVar{constchar*name;char*value;}gSavedVars[]={{"XUL_APP_FILE",nullptr}};staticvoidSaveStateForAppInitiatedRestart(){for(auto&savedVar:gSavedVars){constchar*s=PR_GetEnv(savedVar.name);if(s)savedVar.value=Smprintf("%s=%s",savedVar.name,s).release();}}staticvoidRestoreStateForAppInitiatedRestart(){for(auto&savedVar:gSavedVars){if(savedVar.value)PR_SetEnv(savedVar.value);}}// When we first initialize the crash reporter we don't have a profile,// so we set the minidump path to $TEMP. Once we have a profile,// we set it to $PROFILE/minidumps, creating the directory// if needed.staticvoidMakeOrSetMinidumpPath(nsIFile*profD){nsCOMPtr<nsIFile>dumpD;profD->Clone(getter_AddRefs(dumpD));if(dumpD){boolfileExists;// XXX: do some more error checking heredumpD->Append(NS_LITERAL_STRING("minidumps"));dumpD->Exists(&fileExists);if(!fileExists){nsresultrv=dumpD->Create(nsIFile::DIRECTORY_TYPE,0700);NS_ENSURE_SUCCESS_VOID(rv);}nsAutoStringpathStr;if(NS_SUCCEEDED(dumpD->GetPath(pathStr)))CrashReporter::SetMinidumpPath(pathStr);}}constXREAppData*gAppData=nullptr;#ifdef MOZ_WIDGET_GTKstaticvoidMOZ_gdk_display_close(GdkDisplay*display){# if CLEANUP_MEMORY// XXX wallpaper for bug 417163: don't close the Display if we're using the// Qt theme because we crash (in Qt code) when using jemalloc.boolskip_display_close=false;GtkSettings*settings=gtk_settings_get_for_screen(gdk_display_get_default_screen(display));gchar*theme_name;g_object_get(settings,"gtk-theme-name",&theme_name,nullptr);if(theme_name){skip_display_close=strcmp(theme_name,"Qt")==0;if(skip_display_close)NS_WARNING("wallpaper bug 417163 for Qt theme");g_free(theme_name);}# ifdef MOZ_WIDGET_GTK// A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=703257if(gtk_check_version(3,9,8)!=NULL)skip_display_close=true;# endif// Get a (new) Pango context that holds a reference to the fontmap that// GTK has been using. gdk_pango_context_get() must be called while GTK// has a default display.PangoContext*pangoContext=gdk_pango_context_get();boolbuggyCairoShutdown=cairo_version()<CAIRO_VERSION_ENCODE(1,4,0);if(!buggyCairoShutdown){// We should shut down GDK before we shut down libraries it depends on// like Pango and cairo. But if cairo shutdown is buggy, we should// shut down cairo first otherwise it may crash because of dangling// references to Display objects (see bug 469831).if(!skip_display_close)gdk_display_close(display);}// Clean up PangoCairo's default fontmap.// This pango_fc_font_map_shutdown call (and the associated code to// get the font map) really shouldn't be needed anymore, except that// it's needed to avoid having cairo_debug_reset_static_data fatally// assert if we've leaked other things that hold on to the fontmap,// which is something that currently happens in mochitest-plugins.// Even if it didn't happen in mochitest-plugins, we probably want to// avoid the crash-on-leak problem since it makes it harder to use// many of our leak tools to debug leaks.// This doesn't take a reference.PangoFontMap*fontmap=pango_context_get_font_map(pangoContext);// Do some shutdown of the fontmap, which releases the fonts, clearing a// bunch of circular references from the fontmap through the fonts back to// itself. The shutdown that this does is much less than what's done by// the fontmap's finalize, though.if(PANGO_IS_FC_FONT_MAP(fontmap))pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(fontmap));g_object_unref(pangoContext);// Tell PangoCairo to release its default fontmap.pango_cairo_font_map_set_default(nullptr);// cairo_debug_reset_static_data() is prototyped through cairo.h included// by gtk.h.# ifdef cairo_debug_reset_static_data# error \ "Looks like we're including Mozilla's cairo instead of system cairo"# endifcairo_debug_reset_static_data();// FIXME: Do we need to call this in non-GTK2 cases as well?FcFini();if(buggyCairoShutdown){if(!skip_display_close)gdk_display_close(display);}# else // not CLEANUP_MEMORY// Don't do anything to avoid running into driver bugs under XCloseDisplay().// See bug 973192.(void)display;# endif}#endif/** * NSPR will search for the "nspr_use_zone_allocator" symbol throughout * the process and use it to determine whether the application defines its own * memory allocator or not. * * Since most applications (e.g. Firefox and Thunderbird) don't use any special * allocators and therefore don't define this symbol, NSPR must search the * entire process, which reduces startup performance. * * By defining the symbol here, we can avoid the wasted lookup and hopefully * improve startup performance. */NS_VISIBILITY_DEFAULTPRBoolnspr_use_zone_allocator=PR_FALSE;#ifdef CAIRO_HAS_DWRITE_FONT# include <dwrite.h># ifdef DEBUG_DWRITE_STARTUP# define LOGREGISTRY(msg) LogRegistryEvent(msg)// for use when monitoring processstaticvoidLogRegistryEvent(constwchar_t*msg){HKEYdummyKey;HRESULThr;wchar_tbuf[512];wsprintf(buf,L" log %s",msg);hr=RegOpenKeyEx(HKEY_LOCAL_MACHINE,buf,0,KEY_READ,&dummyKey);if(SUCCEEDED(hr)){RegCloseKey(dummyKey);}}# else# define LOGREGISTRY(msg)# endifstaticDWORDWINAPIInitDwriteBG(LPVOIDlpdwThreadParam){SetThreadPriority(GetCurrentThread(),THREAD_MODE_BACKGROUND_BEGIN);LOGREGISTRY(L"loading dwrite.dll");HMODULEdwdll=LoadLibraryW(L"dwrite.dll");if(dwdll){decltype(DWriteCreateFactory)*createDWriteFactory=(decltype(DWriteCreateFactory)*)GetProcAddress(dwdll,"DWriteCreateFactory");if(createDWriteFactory){LOGREGISTRY(L"creating dwrite factory");IDWriteFactory*factory;HRESULThr=createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED,__uuidof(IDWriteFactory),reinterpret_cast<IUnknown**>(&factory));if(SUCCEEDED(hr)){LOGREGISTRY(L"dwrite factory done");factory->Release();LOGREGISTRY(L"freed factory");}else{LOGREGISTRY(L"failed to create factory");}}}SetThreadPriority(GetCurrentThread(),THREAD_MODE_BACKGROUND_END);return0;}#endif#ifdef USE_GLX_TESTboolfire_glxtest_process();#endif#include"GeckoProfiler.h"// Encapsulates startup and shutdown state for XRE_mainclassXREMain{public:XREMain():mStartOffline(false),mShuttingDown(false)#if defined(MOZ_WIDGET_GTK),mDisableRemote(false),mGdkDisplay(nullptr)#endif{};~XREMain(){mScopedXPCOM=nullptr;mAppData=nullptr;}intXRE_main(intargc,char*argv[],constBootstrapConfig&aConfig);intXRE_mainInit(bool*aExitFlag);intXRE_mainStartup(bool*aExitFlag);nsresultXRE_mainRun();Result<bool,nsresult>CheckLastStartupWasCrash();nsCOMPtr<nsINativeAppSupport>mNativeApp;nsCOMPtr<nsIToolkitProfileService>mProfileSvc;nsCOMPtr<nsIFile>mProfD;nsCOMPtr<nsIFile>mProfLD;nsCOMPtr<nsIProfileLock>mProfileLock;#if defined(MOZ_WIDGET_GTK)nsCOMPtr<nsIRemoteService>mRemoteService;nsProfileLockmRemoteLock;nsCOMPtr<nsIFile>mRemoteLockDir;#endifUniquePtr<ScopedXPCOMStartup>mScopedXPCOM;UniquePtr<XREAppData>mAppData;nsXREDirProvidermDirProvider;nsAutoCStringmProfileName;nsAutoCStringmDesktopStartupID;boolmStartOffline;boolmShuttingDown;#if defined(MOZ_WIDGET_GTK)boolmDisableRemote;#endif#if defined(MOZ_WIDGET_GTK)GdkDisplay*mGdkDisplay;#endif};#if defined(XP_UNIX) && !defined(ANDROID)staticSmprintfPointerFormatUid(uid_taId){if(constautopw=getpwuid(aId)){returnmozilla::Smprintf("%s",pw->pw_name);}returnmozilla::Smprintf("uid %d",static_cast<int>(aId));}// Bug 1323302: refuse to run under sudo or similar.staticboolCheckForUserMismatch(){staticcharconst*constkVars[]={"HOME",# ifdef MOZ_WIDGET_GTK"XDG_RUNTIME_DIR",# endif# ifdef MOZ_X11"XAUTHORITY",# endif};constuid_teuid=geteuid();if(euid!=0){// On Linux it's possible to have superuser capabilities with a// nonzero uid, but anyone who knows enough to make that happen// probably knows enough to debug the resulting problems.// Otherwise, a non-root user can't cause the problems we're// concerned about.returnfalse;}for(constautovar:kVars){if(constautopath=PR_GetEnv(var)){structstatst;if(stat(path,&st)==0){if(st.st_uid!=euid){constautoowner=FormatUid(st.st_uid);Output(true,"Running "MOZ_APP_DISPLAYNAME" as root in a regular"" user's session is not supported. ($%s is %s which is"" owned by %s.)\n",var,path,owner.get());returntrue;}}}}returnfalse;}#else // !XP_UNIX || ANDROIDstaticboolCheckForUserMismatch(){returnfalse;}#endifstaticvoidIncreaseDescriptorLimits(){#ifdef XP_UNIX// Increase the fd limit to accomodate IPC resources like shared memory.staticconstrlim_tkFDs=4096;structrlimitrlim;if(getrlimit(RLIMIT_NOFILE,&rlim)!=0){Output(false,"getrlimit: %s\n",strerror(errno));return;}// Don't decrease the limit if it's already high enough, but don't// try to go over the hard limit. (RLIM_INFINITY isn't required to// be the numerically largest rlim_t, so don't assume that.)if(rlim.rlim_cur!=RLIM_INFINITY&&rlim.rlim_cur<kFDs&&rlim.rlim_cur<rlim.rlim_max){if(rlim.rlim_max!=RLIM_INFINITY&&rlim.rlim_max<kFDs){rlim.rlim_cur=rlim.rlim_max;}else{rlim.rlim_cur=kFDs;}if(setrlimit(RLIMIT_NOFILE,&rlim)!=0){Output(false,"setrlimit: %s\n",strerror(errno));}}#endif}/* * XRE_mainInit - Initial setup and command line parameter processing. * Main() will exit early if either return value != 0 or if aExitFlag is * true. */intXREMain::XRE_mainInit(bool*aExitFlag){if(!aExitFlag)return1;*aExitFlag=false;atexit(UnexpectedExit);autoexpectedShutdown=mozilla::MakeScopeExit([&]{MozExpectedExit();});StartupTimeline::Record(StartupTimeline::MAIN);if(CheckForUserMismatch()){return1;}if(PR_GetEnv("MOZ_CHAOSMODE")){ChaosFeaturefeature=ChaosFeature::Any;longfeatureInt=strtol(PR_GetEnv("MOZ_CHAOSMODE"),nullptr,16);if(featureInt){// NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.feature=static_cast<ChaosFeature>(featureInt);}ChaosMode::SetChaosFeature(feature);}#ifdef MOZ_ASAN_REPORTER// In ASan Reporter builds, we enable certain chaos features by default unless// the user explicitly requests a particular set of features.if(!PR_GetEnv("MOZ_CHAOSMODE")){ChaosMode::SetChaosFeature(static_cast<ChaosFeature>(ChaosFeature::ThreadScheduling|ChaosFeature::NetworkScheduling|ChaosFeature::TimerScheduling));}#endifif(ChaosMode::isActive(ChaosFeature::Any)){printf_stderr("*** You are running in chaos test mode. See ChaosMode.h. ***\n");}if(CheckArg("headless")||CheckArgExists("screenshot")){PR_SetEnv("MOZ_HEADLESS=1");}if(gfxPlatform::IsHeadless()){#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)printf_stderr("*** You are running in headless mode.\n");#elseOutput(true,"Error: headless mode is not currently supported on this platform.\n");return1;#endif#ifdef XP_MACOSX// To avoid taking focus when running in headless mode immediately// transition Firefox to a background application.ProcessSerialNumberpsn={0,kCurrentProcess};OSStatustransformStatus=TransformProcessType(&psn,kProcessTransformToBackgroundApplication);if(transformStatus!=noErr){NS_ERROR("Failed to make process a background application.");return1;}#endif}nsresultrv;ArgResultar;#ifdef DEBUGif(PR_GetEnv("XRE_MAIN_BREAK"))NS_BREAK();#endifIncreaseDescriptorLimits();#ifdef USE_GLX_TEST// bug 639842 - it's very important to fire this process BEFORE we set up// error handling. indeed, this process is expected to be crashy, and we// don't want the user to see its crashes. That's the whole reason for// doing this in a separate process.//// This call will cause a fork and the fork will terminate itself separately// from the usual shutdown sequencefire_glxtest_process();#endifSetupErrorHandling(gArgv[0]);#ifdef CAIRO_HAS_DWRITE_FONT{// Bug 602792 - when DWriteCreateFactory is called the dwrite client dll// starts the FntCache service if it isn't already running (it's set// to manual startup by default in Windows 7 RTM). Subsequent DirectWrite// calls cause the IDWriteFactory object to communicate with the FntCache// service with a timeout; if there's no response after the timeout, the// DirectWrite client library will assume the service isn't around and do// manual font file I/O on _all_ system fonts. To avoid this, load the// dwrite library and create a factory as early as possible so that the// FntCache service is ready by the time it's needed.CreateThread(nullptr,0,&InitDwriteBG,nullptr,0,nullptr);}#endif#ifdef XP_UNIXconstchar*home=PR_GetEnv("HOME");if(!home||!*home){structpasswd*pw=getpwuid(geteuid());if(!pw||!pw->pw_dir){Output(true,"Could not determine HOME directory");return1;}SaveWordToEnv("HOME",nsDependentCString(pw->pw_dir));}#endif#ifdef MOZ_ACCESSIBILITY_ATK// Suppress atk-bridge init at startup, until mozilla accessibility is// initialized. This works after gnome 2.24.2.SaveToEnv("NO_AT_BRIDGE=1");#endif// Check for application.ini overridesconstchar*override=nullptr;ar=CheckArg("override",&override,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){Output(true,"Incorrect number of arguments passed to --override");return1;}if(ar==ARG_FOUND){nsCOMPtr<nsIFile>overrideLF;rv=XRE_GetFileFromPath(override,getter_AddRefs(overrideLF));if(NS_FAILED(rv)){Output(true,"Error: unrecognized override.ini path.\n");return1;}rv=XRE_ParseAppData(overrideLF,*mAppData);if(NS_FAILED(rv)){Output(true,"Couldn't read override.ini");return1;}}// Check sanity and correctness of app data.if(!mAppData->name){Output(true,"Error: App:Name not specified in application.ini\n");return1;}if(!mAppData->buildID){Output(true,"Error: App:BuildID not specified in application.ini\n");return1;}// XXX Originally ScopedLogging was here? Now it's in XRE_main above// XRE_mainInit.if(!mAppData->minVersion){Output(true,"Error: Gecko:MinVersion not specified in application.ini\n");return1;}if(!mAppData->maxVersion){// If no maxVersion is specified, we assume the app is only compatible// with the initial preview release. Do not increment this number ever!mAppData->maxVersion="1.*";}if(mozilla::Version(mAppData->minVersion)>gToolkitVersion||mozilla::Version(mAppData->maxVersion)<gToolkitVersion){Output(true,"Error: Platform version '%s' is not compatible with\n""minVersion >= %s\nmaxVersion <= %s\n",(constchar*)gToolkitVersion,(constchar*)mAppData->minVersion,(constchar*)mAppData->maxVersion);return1;}rv=mDirProvider.Initialize(mAppData->directory,mAppData->xreDirectory);if(NS_FAILED(rv))return1;if(EnvHasValue("MOZ_CRASHREPORTER")){mAppData->flags|=NS_XRE_ENABLE_CRASH_REPORTER;}nsCOMPtr<nsIFile>xreBinDirectory;xreBinDirectory=mDirProvider.GetGREBinDir();if((mAppData->flags&NS_XRE_ENABLE_CRASH_REPORTER)&&NS_SUCCEEDED(CrashReporter::SetExceptionHandler(xreBinDirectory))){nsCOMPtr<nsIFile>file;rv=nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(file));if(NS_SUCCEEDED(rv)){CrashReporter::SetUserAppDataDirectory(file);}if(mAppData->crashReporterURL)CrashReporter::SetServerURL(nsDependentCString(mAppData->crashReporterURL));// We overwrite this once we finish starting up.CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::StartupCrash,true);// pass some basic info from the app dataif(mAppData->vendor)CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::Vendor,nsDependentCString(mAppData->vendor));if(mAppData->name)CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::ProductName,nsDependentCString(mAppData->name));if(mAppData->ID)CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::ProductID,nsDependentCString(mAppData->ID));if(mAppData->version)CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::Version,nsDependentCString(mAppData->version));if(mAppData->buildID)CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::BuildID,nsDependentCString(mAppData->buildID));nsDependentCStringreleaseChannel(NS_STRINGIFY(MOZ_UPDATE_CHANNEL));CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::ReleaseChannel,releaseChannel);#ifdef MOZ_LINKERCrashReporter::AnnotateCrashReport(CrashReporter::Annotation::CrashAddressLikelyWrong,IsSignalHandlingBroken());#endif#ifdef XP_WINnsAutoStringappInitDLLs;if(widget::WinUtils::GetAppInitDLLs(appInitDLLs)){CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::AppInitDLLs,NS_ConvertUTF16toUTF8(appInitDLLs));}#endifCrashReporter::SetRestartArgs(gArgc,gArgv);// annotate other data (user id etc)nsCOMPtr<nsIFile>userAppDataDir;if(NS_SUCCEEDED(mDirProvider.GetUserAppDataDirectory(getter_AddRefs(userAppDataDir)))){CrashReporter::SetupExtraData(userAppDataDir,nsDependentCString(mAppData->buildID));// see if we have a crashreporter-override.ini in the application// directorynsCOMPtr<nsIFile>overrideini;boolexists;if(NS_SUCCEEDED(mDirProvider.GetAppDir()->Clone(getter_AddRefs(overrideini)))&&NS_SUCCEEDED(overrideini->AppendNative(NS_LITERAL_CSTRING("crashreporter-override.ini")))&&NS_SUCCEEDED(overrideini->Exists(&exists))&&exists){#ifdef XP_WINnsAutoStringoverridePathW;overrideini->GetPath(overridePathW);NS_ConvertUTF16toUTF8overridePath(overridePathW);#elsensAutoCStringoverridePath;overrideini->GetNativePath(overridePath);#endifSaveWordToEnv("MOZ_CRASHREPORTER_STRINGS_OVERRIDE",overridePath);}}}#if defined(MOZ_SANDBOX) && defined(XP_WIN)if(mAppData->sandboxBrokerServices){SandboxBroker::Initialize(mAppData->sandboxBrokerServices);}else{# if defined(MOZ_CONTENT_SANDBOX)// If we're sandboxing content and we fail to initialize, then crashing here// seems like the sensible option.if(BrowserTabsRemoteAutostart()){MOZ_CRASH("Failed to initialize broker services, can't continue.");}# endif// Otherwise just warn for the moment, as most things will work.NS_WARNING("Failed to initialize broker services, sandboxed processes will ""fail to start.");}if(mAppData->sandboxPermissionsService){SandboxPermissions::Initialize(mAppData->sandboxPermissionsService,nullptr);}#endif#ifdef XP_MACOSX// Set up ability to respond to system (Apple) events. This must occur before// ProcessUpdates to ensure that links clicked in external applications aren't// lost when updates are pending.SetupMacApplicationDelegate();if(EnvHasValue("MOZ_LAUNCHED_CHILD")){// This is needed, on relaunch, to force the OS to use the "Cocoa Dock// API". Otherwise the call to ReceiveNextEvent() below will make it// use the "Carbon Dock API". For more info see bmo bug 377166.EnsureUseCocoaDockAPI();// When the app relaunches, the original process exits. This causes// the dock tile to stop bouncing, lose the "running" triangle, and// if the tile does not permanently reside in the Dock, even disappear.// This can be confusing to the user, who is expecting the app to launch.// Calling ReceiveNextEvent without requesting any event is enough to// cause a dock tile for the child process to appear.constEventTypeSpeckFakeEventList[]={{INT_MAX,INT_MAX}};EventRefevent;::ReceiveNextEvent(GetEventTypeCount(kFakeEventList),kFakeEventList,kEventDurationNoWait,false,&event);}if(CheckArg("foreground")){// The original process communicates that it was in the foreground by// adding this argument. This new process, which is taking over for// the old one, should make itself the active application.ProcessSerialNumberpsn;if(::GetCurrentProcess(&psn)==noErr)::SetFrontProcess(&psn);}#endifSaveToEnv("MOZ_LAUNCHED_CHILD=");// On Windows, the -os-restarted command line switch lets us know when we are// restarted via RegisterApplicationRestart. May be used for other OSes later.if(CheckArg("os-restarted",nullptr,CheckArgFlag::RemoveArg)==ARG_FOUND){gRestartedByOS=true;}gRestartArgc=gArgc;gRestartArgv=(char**)malloc(sizeof(char*)*(gArgc+1+(override?2:0)));if(!gRestartArgv){return1;}inti;for(i=0;i<gArgc;++i){gRestartArgv[i]=gArgv[i];}// Add the -override argument back (it is removed automatically be CheckArg)// if there is oneif(override){gRestartArgv[gRestartArgc++]=const_cast<char*>("-override");gRestartArgv[gRestartArgc++]=const_cast<char*>(override);}gRestartArgv[gRestartArgc]=nullptr;Maybe<bool>safeModeRequested=IsSafeModeRequested(gArgc,gArgv);if(!safeModeRequested){return1;}gSafeMode=safeModeRequested.value();#ifdef XP_WIN{// Add CPU microcode version to the crash report as "CPUMicrocodeVersion".// It feels like this code may belong in nsSystemInfo instead.intcpuUpdateRevision=-1;HKEYkey;staticconstWCHARkeyName[]=L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,keyName,0,KEY_QUERY_VALUE,&key)==ERROR_SUCCESS){DWORDupdateRevision[2];DWORDlen=sizeof(updateRevision);DWORDvtype;// Windows 7 uses "Update Signature", 8 uses "Update Revision".// For AMD CPUs, "CurrentPatchLevel" is sometimes used.// Take the first one we find.LPCWSTRchoices[]={L"Update Signature",L"Update Revision",L"CurrentPatchLevel"};for(size_toneChoice=0;oneChoice<ArrayLength(choices);oneChoice++){if(RegQueryValueExW(key,choices[oneChoice],0,&vtype,reinterpret_cast<LPBYTE>(updateRevision),&len)==ERROR_SUCCESS){if(vtype==REG_BINARY&&len==sizeof(updateRevision)){// The first word is unusedcpuUpdateRevision=static_cast<int>(updateRevision[1]);break;}elseif(vtype==REG_DWORD&&len==sizeof(updateRevision[0])){cpuUpdateRevision=static_cast<int>(updateRevision[0]);break;}}}}if(cpuUpdateRevision>0){CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::CPUMicrocodeVersion,nsPrintfCString("0x%x",cpuUpdateRevision));}}#endifCrashReporter::AnnotateCrashReport(CrashReporter::Annotation::SafeMode,gSafeMode);// Handle --no-remote and --new-instance command line arguments. Setup// the environment to better accommodate other components and various// restart scenarios.ar=CheckArg("no-remote",nullptr,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --no-remote is invalid when argument --osint ""is specified\n");return1;}if(ar==ARG_FOUND){SaveToEnv("MOZ_NO_REMOTE=1");}ar=CheckArg("new-instance",nullptr,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --new-instance is invalid when argument ""--osint is specified\n");return1;}if(ar==ARG_FOUND){SaveToEnv("MOZ_NEW_INSTANCE=1");}// Handle --help and --version command line arguments.// They should return quickly, so we deal with them here.if(CheckArg("h")||CheckArg("help")||CheckArg("?")){DumpHelp();*aExitFlag=true;return0;}if(CheckArg("v")||CheckArg("version")){DumpVersion();*aExitFlag=true;return0;}rv=XRE_InitCommandLine(gArgc,gArgv);NS_ENSURE_SUCCESS(rv,1);// Check for --register, which registers chrome and then exits immediately.ar=CheckArg("register",nullptr,CheckArgFlag::CheckOSInt|CheckArgFlag::RemoveArg);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --register is invalid when argument --osint is ""specified\n");return1;}if(ar==ARG_FOUND){ScopedXPCOMStartupxpcom;rv=xpcom.Initialize();NS_ENSURE_SUCCESS(rv,1);{nsCOMPtr<nsIChromeRegistry>chromeReg=mozilla::services::GetChromeRegistryService();NS_ENSURE_TRUE(chromeReg,1);chromeReg->CheckForNewChrome();}*aExitFlag=true;return0;}return0;}#ifdef XP_WINstaticboolQueryOneWMIProperty(IWbemServices*aServices,constwchar_t*aWMIClass,constwchar_t*aProperty,VARIANT*aResult){RefPtr<IEnumWbemClassObject>enumerator;_bstr_tquery(L"SELECT * FROM ");query+=_bstr_t(aWMIClass);HRESULThr=aServices->ExecQuery(_bstr_t(L"WQL"),query,WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY,nullptr,getter_AddRefs(enumerator));if(FAILED(hr)||!enumerator){returnfalse;}RefPtr<IWbemClassObject>classObject;ULONGresults;hr=enumerator->Next(WBEM_INFINITE,1,getter_AddRefs(classObject),&results);if(FAILED(hr)||results==0){returnfalse;}hr=classObject->Get(aProperty,0,aResult,0,0);returnSUCCEEDED(hr);}/** * Uses WMI to read some information that may be useful for diagnosing * crashes. This function is best-effort; failures shouldn't burden the * caller. COM must be initialized before calling. */staticconstcharkMemoryErrorCorrectionValues[][15]={"Reserved",// 0"Other",// 1"Unknown",// 2"None",// 3"Parity",// 4"Single-bit ECC",// 5"Multi-bit ECC",// 6"CRC"// 7};staticvoidAnnotateWMIData(){RefPtr<IWbemLocator>locator;HRESULThr=CoCreateInstance(CLSID_WbemLocator,nullptr,CLSCTX_INPROC_SERVER,IID_IWbemLocator,getter_AddRefs(locator));if(FAILED(hr)){return;}RefPtr<IWbemServices>services;hr=locator->ConnectServer(_bstr_t(L"ROOT\\CIMV2"),nullptr,nullptr,nullptr,0,nullptr,nullptr,getter_AddRefs(services));if(FAILED(hr)){return;}hr=CoSetProxyBlanket(services,RPC_C_AUTHN_WINNT,RPC_C_AUTHZ_NONE,nullptr,RPC_C_AUTHN_LEVEL_CALL,RPC_C_IMP_LEVEL_IMPERSONATE,nullptr,EOAC_NONE);if(FAILED(hr)){return;}VARIANTvalue;VariantInit(&value);// Annotate information about the system manufacturer.if(QueryOneWMIProperty(services,L"Win32_BIOS",L"Manufacturer",&value)&&V_VT(&value)==VT_BSTR){CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::BIOS_Manufacturer,NS_ConvertUTF16toUTF8(V_BSTR(&value)));}VariantClear(&value);// Annotate information about type of memory error correction.if(QueryOneWMIProperty(services,L"Win32_PhysicalMemoryArray",L"MemoryErrorCorrection",&value)&&V_VT(&value)==VT_I4){longvalueInt=V_I4(&value);nsCStringvalueString;if(valueInt<0||valueInt>=long(ArrayLength(kMemoryErrorCorrectionValues))){valueString.AssignLiteral("Unexpected value");}else{valueString.AssignASCII(kMemoryErrorCorrectionValues[valueInt]);}CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::MemoryErrorCorrection,valueString);}VariantClear(&value);}staticvoidPR_CALLBACKAnnotateWMIData_ThreadStart(void*){HRESULThr=CoInitialize(nullptr);if(FAILED(hr)){return;}AnnotateWMIData();CoUninitialize();}#endif // XP_WIN#if defined(XP_LINUX) && !defined(ANDROID)staticvoidAnnotateLSBRelease(void*){nsCStringdist,desc,release,codename;if(widget::lsb::GetLSBRelease(dist,desc,release,codename)){CrashReporter::AppendAppNotesToCrashReport(desc);}}#endif // defined(XP_LINUX) && !defined(ANDROID)#ifdef XP_WINstaticvoidReadAheadDll(constwchar_t*dllName){wchar_tdllPath[MAX_PATH];if(ConstructSystem32Path(dllName,dllPath,MAX_PATH)){ReadAheadLib(dllPath);}}staticvoidPR_CALLBACKReadAheadDlls_ThreadStart(void*){// Load DataExchange.dll and twinapi.appcore.dll for nsWindow::EnableDragDropReadAheadDll(L"DataExchange.dll");ReadAheadDll(L"twinapi.appcore.dll");// Load twinapi.dll for WindowsUIUtils::UpdateTabletModeStateReadAheadDll(L"twinapi.dll");// Load explorerframe.dll for WinTaskbar::InitializeReadAheadDll(L"ExplorerFrame.dll");}#endifnamespacemozilla{ShutdownChecksModegShutdownChecks=SCM_NOTHING;}// namespace mozillastaticvoidSetShutdownChecks(){// Set default first. On debug builds we crash. On nightly and local// builds we record. Nightlies will then send the info via telemetry,// but it is usefull to have the data in about:telemetry in local builds// too.#ifdef DEBUG# if defined(MOZ_CODE_COVERAGE)gShutdownChecks=SCM_NOTHING;# elsegShutdownChecks=SCM_CRASH;# endif // MOZ_CODE_COVERAGE#elseconstchar*releaseChannel=NS_STRINGIFY(MOZ_UPDATE_CHANNEL);if(strcmp(releaseChannel,"nightly")==0||strcmp(releaseChannel,"default")==0){gShutdownChecks=SCM_RECORD;}else{gShutdownChecks=SCM_NOTHING;}#endif // DEBUG// We let an environment variable override the default so that addons// authors can use it for debugging shutdown with released firefox versions.constchar*mozShutdownChecksEnv=PR_GetEnv("MOZ_SHUTDOWN_CHECKS");if(mozShutdownChecksEnv){if(strcmp(mozShutdownChecksEnv,"crash")==0){gShutdownChecks=SCM_CRASH;}elseif(strcmp(mozShutdownChecksEnv,"record")==0){gShutdownChecks=SCM_RECORD;}elseif(strcmp(mozShutdownChecksEnv,"nothing")==0){gShutdownChecks=SCM_NOTHING;}}}namespacemozilla{namespacestartup{Result<nsCOMPtr<nsIFile>,nsresult>GetIncompleteStartupFile(nsIFile*aProfLD){nsCOMPtr<nsIFile>crashFile;MOZ_TRY(aProfLD->Clone(getter_AddRefs(crashFile)));MOZ_TRY(crashFile->Append(FILE_STARTUP_INCOMPLETE));returnstd::move(crashFile);}}// namespace startup}// namespace mozilla// Check whether the last startup attempt resulted in a crash within the// last 6 hours.// Note that this duplicates the logic in nsAppStartup::TrackStartupCrashBegin,// which runs too late for our purposes.Result<bool,nsresult>XREMain::CheckLastStartupWasCrash(){constexprint32_tMAX_TIME_SINCE_STARTUP=6*60*60*1000;nsCOMPtr<nsIFile>crashFile;MOZ_TRY_VAR(crashFile,GetIncompleteStartupFile(mProfLD));// Attempt to create the incomplete startup canary file. If the file already// exists, this fails, and we know the last startup was a success. If it// doesn't already exist, it is created, and will be removed at the end of// the startup crash detection window.AutoFDClosefd;Unused<<crashFile->OpenNSPRFileDesc(PR_WRONLY|PR_CREATE_FILE|PR_EXCL,0666,&fd.rwget());if(fd){returnfalse;}PRTimelastModifiedTime;MOZ_TRY(crashFile->GetLastModifiedTime(&lastModifiedTime));// If the file exists, and was created within the appropriate time window,// the last startup was recent and resulted in a crash.PRTimenow=PR_Now()/PR_USEC_PER_MSEC;returnnow-lastModifiedTime<=MAX_TIME_SINCE_STARTUP;}/* * XRE_mainStartup - Initializes the profile and various other services. * Main() will exit early if either return value != 0 or if aExitFlag is * true. */intXREMain::XRE_mainStartup(bool*aExitFlag){nsresultrv;if(!aExitFlag)return1;*aExitFlag=false;SetShutdownChecks();// Enable Telemetry IO Reporting on DEBUG, nightly and local builds#ifdef DEBUGmozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);#else{constchar*releaseChannel=NS_STRINGIFY(MOZ_UPDATE_CHANNEL);if(strcmp(releaseChannel,"nightly")==0||strcmp(releaseChannel,"default")==0){mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);}}#endif /* DEBUG */#if defined(XP_WIN)// Enable the HeapEnableTerminationOnCorruption exploit mitigation. We ignore// the return code because it always returns success, although it has no// effect on Windows older than XP SP3.HeapSetInformation(NULL,HeapEnableTerminationOnCorruption,NULL,0);#endif /* XP_WIN */#if defined(MOZ_WIDGET_GTK)// Stash DESKTOP_STARTUP_ID in malloc'ed memory because gtk_init will clear// it.# define HAVE_DESKTOP_STARTUP_IDconstchar*desktopStartupIDEnv=PR_GetEnv("DESKTOP_STARTUP_ID");if(desktopStartupIDEnv){mDesktopStartupID.Assign(desktopStartupIDEnv);}#endif#if defined(MOZ_WIDGET_GTK)// setup for private colormap. Ideally we'd like to do this// in nsAppShell::Create, but we need to get in before gtk// has been initialized to make sure everything is running// consistently.// Set program name to the one defined in application.ini.{nsAutoCStringprogram(gAppData->name);ToLowerCase(program);g_set_prgname(program.get());}// Initialize GTK here for splash.# if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11)// Disable XInput2 multidevice support due to focus bugginess.// See bugs 1182700, 1170342.// gdk_disable_multidevice() affects Gdk X11 backend only,// the multidevice support is always enabled on Wayland backend.constchar*useXI2=PR_GetEnv("MOZ_USE_XINPUT2");if(!useXI2||(*useXI2=='0'))gdk_disable_multidevice();# endif// Open the display ourselves instead of using gtk_init, so that we can// close it without fear that one day gtk might clean up the display it// opens.if(!gtk_parse_args(&gArgc,&gArgv))return1;#endif /* MOZ_WIDGET_GTK */#ifdef FUZZINGif(PR_GetEnv("FUZZER")){*aExitFlag=true;returnmozilla::fuzzerRunner->Run(&gArgc,&gArgv);}#endifif(PR_GetEnv("MOZ_RUN_GTEST")){intresult;#ifdef XP_WINUseParentConsole();#endif// RunGTest will only be set if we're in xul-unitif(mozilla::RunGTest){gIsGtest=true;result=mozilla::RunGTest(&gArgc,gArgv);gIsGtest=false;}else{result=1;printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");}*aExitFlag=true;returnresult;}#ifdef MOZ_X11// Init X11 in thread-safe mode. Must be called prior to the first call to// XOpenDisplay (called inside gdk_display_open). This is a requirement for// off main tread compositing.if(!gfxPlatform::IsHeadless()){XInitThreads();}#endif#if defined(MOZ_WIDGET_GTK)if(!gfxPlatform::IsHeadless()){constchar*display_name=nullptr;boolsaveDisplayArg=false;// display_name is owned by gdk.display_name=gdk_get_display_arg_name();// if --display argument is given make sure it's// also passed to ContentChild::Init() by MOZ_GDK_DISPLAY.if(display_name){SaveWordToEnv("MOZ_GDK_DISPLAY",nsDependentCString(display_name));saveDisplayArg=true;}booldisableWayland=true;# if defined(MOZ_WAYLAND)// Enable Wayland on Gtk+ >= 3.22 where we can expect recent enough// compositor & libwayland interface.disableWayland=(gtk_check_version(3,22,0)!=nullptr);if(!disableWayland){// Make X11 backend the default one unless MOZ_ENABLE_WAYLAND or// GDK_BACKEND are specified.disableWayland=(PR_GetEnv("GDK_BACKEND")==nullptr)&&(PR_GetEnv("MOZ_ENABLE_WAYLAND")==nullptr);}# endif// On Wayland disabled builds read X11 DISPLAY env exclusively// and don't care about different displays.if(disableWayland&&!display_name){display_name=PR_GetEnv("DISPLAY");if(!display_name){PR_fprintf(PR_STDERR,"Error: no DISPLAY environment variable specified\n");return1;}}if(display_name){mGdkDisplay=gdk_display_open(display_name);if(!mGdkDisplay){PR_fprintf(PR_STDERR,"Error: cannot open display: %s\n",display_name);return1;}gdk_display_manager_set_default_display(gdk_display_manager_get(),mGdkDisplay);if(saveDisplayArg){if(GDK_IS_X11_DISPLAY(mGdkDisplay)){SaveWordToEnv("DISPLAY",nsDependentCString(display_name));}# ifdef MOZ_WAYLANDelseif(!GDK_IS_X11_DISPLAY(mGdkDisplay)){SaveWordToEnv("WAYLAND_DISPLAY",nsDependentCString(display_name));}# endif}}# ifdef MOZ_WIDGET_GTKelse{mGdkDisplay=gdk_display_manager_open_display(gdk_display_manager_get(),nullptr);}# endif}else{mDisableRemote=true;}#endif#if defined(MOZ_WIDGET_GTK)// handle --remote now that xpcom is fired upboolnewInstance;{char*e=PR_GetEnv("MOZ_NO_REMOTE");mDisableRemote=(mDisableRemote||(e&&*e));if(mDisableRemote){newInstance=true;}else{e=PR_GetEnv("MOZ_NEW_INSTANCE");newInstance=(e&&*e);}}if(!newInstance){nsAutoCStringprogram(gAppData->remotingName);ToLowerCase(program);constchar*username=getenv("LOGNAME");constchar*profile=nullptr;RemoteResultrr=ParseRemoteCommandLine(program,&profile,&username);if(rr==REMOTE_ARG_BAD){return1;}if(!username){structpasswd*pw=getpwuid(geteuid());if(pw&&pw->pw_name){// Beware that another call to getpwent/getpwname/getpwuid will// overwrite pw, but we don't have such another call between here and// when username is used last.username=pw->pw_name;}}nsCOMPtr<nsIFile>mutexDir;rv=GetSpecialSystemDirectory(OS_TemporaryDirectory,getter_AddRefs(mutexDir));if(NS_SUCCEEDED(rv)){nsAutoCStringmutexPath=program+NS_LITERAL_CSTRING("_");// In the unlikely even that LOGNAME is not set and getpwuid failed, just// don't put the username in the mutex directory. It will conflict with// other users mutex, but the worst that can happen is that they wait for// MOZ_XREMOTE_START_TIMEOUT_SEC during startup in that case.if(username){mutexPath.Append(username);}if(profile){mutexPath.Append(NS_LITERAL_CSTRING("_")+nsDependentCString(profile));}mutexDir->AppendNative(mutexPath);rv=mutexDir->Create(nsIFile::DIRECTORY_TYPE,0700);if(NS_SUCCEEDED(rv)||rv==NS_ERROR_FILE_ALREADY_EXISTS){mRemoteLockDir=mutexDir;}}if(mRemoteLockDir){constTimeStampepoch=mozilla::TimeStamp::Now();do{rv=mRemoteLock.Lock(mRemoteLockDir,nullptr);if(NS_SUCCEEDED(rv))break;sched_yield();}while((TimeStamp::Now()-epoch)<TimeDuration::FromSeconds(MOZ_XREMOTE_START_TIMEOUT_SEC));if(NS_FAILED(rv)){NS_WARNING("Cannot lock XRemote start mutex");}}// Try to remote the entire command line. If this fails, start up normally.constchar*desktopStartupIDPtr=mDesktopStartupID.IsEmpty()?nullptr:mDesktopStartupID.get();rr=StartRemoteClient(desktopStartupIDPtr,program,profile,username);if(rr==REMOTE_FOUND){*aExitFlag=true;return0;}if(rr==REMOTE_ARG_BAD){return1;}}#endif#if defined(MOZ_WIDGET_GTK)g_set_application_name(mAppData->name);gtk_window_set_auto_startup_notification(false);#endif /* defined(MOZ_WIDGET_GTK) */#ifdef MOZ_X11// Do this after initializing GDK, or GDK will install its own handler.XRE_InstallX11ErrorHandler();#endif// Call the code to install our handler#ifdef MOZ_JPROFsetupProfilingStuff();#endifrv=NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));if(NS_FAILED(rv))return1;boolcanRun=false;rv=mNativeApp->Start(&canRun);if(NS_FAILED(rv)||!canRun){return1;}#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)// DESKTOP_STARTUP_ID is cleared now,// we recover it in case we need a restart.if(!mDesktopStartupID.IsEmpty()){nsAutoCStringdesktopStartupEnv;desktopStartupEnv.AssignLiteral("DESKTOP_STARTUP_ID=");desktopStartupEnv.Append(mDesktopStartupID);// Leak it with extreme prejudice!PR_SetEnv(ToNewCString(desktopStartupEnv));}#endif// Support exiting early for testing startup sequence. Bug 1360493if(CheckArg("test-launch-without-hang")){*aExitFlag=true;return0;}#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)// Check for and process any available updatesnsCOMPtr<nsIFile>updRoot;boolpersistent;rv=mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR,&persistent,getter_AddRefs(updRoot));// XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failedif(NS_FAILED(rv))updRoot=mDirProvider.GetAppDir();// If the MOZ_TEST_PROCESS_UPDATES environment variable already exists, then// we are being called from the callback application.if(EnvHasValue("MOZ_TEST_PROCESS_UPDATES")){// If the caller has asked us to log our arguments, do so. This is used// to make sure that the maintenance service successfully launches the// callback application.constchar*logFile=nullptr;if(ARG_FOUND==CheckArg("dump-args",&logFile)){FILE*logFP=fopen(logFile,"wb");if(logFP){for(inti=1;i<gRestartArgc;++i){fprintf(logFP,"%s\n",gRestartArgv[i]);}fclose(logFP);}}*aExitFlag=true;return0;}// Support for processing an update and exiting. The MOZ_TEST_PROCESS_UPDATES// environment variable will be part of the updater's environment and the// application that is relaunched by the updater. When the application is// relaunched by the updater it will be removed below and the application// will exit.if(CheckArg("test-process-updates")){SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");}nsCOMPtr<nsIFile>exeFile,exeDir;rv=mDirProvider.GetFile(XRE_EXECUTABLE_FILE,&persistent,getter_AddRefs(exeFile));NS_ENSURE_SUCCESS(rv,1);rv=exeFile->GetParent(getter_AddRefs(exeDir));NS_ENSURE_SUCCESS(rv,1);ProcessUpdates(mDirProvider.GetGREDir(),exeDir,updRoot,gRestartArgc,gRestartArgv,mAppData->version);if(EnvHasValue("MOZ_TEST_PROCESS_UPDATES")){SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");*aExitFlag=true;return0;}#endifrv=NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));if(rv==NS_ERROR_FILE_ACCESS_DENIED){PR_fprintf(PR_STDERR,"Error: Access was denied while trying to open files in ""your profile directory.\n");}if(NS_FAILED(rv)){// We failed to choose or create profile - notify user and quitProfileMissingDialog(mNativeApp);return1;}rv=SelectProfile(getter_AddRefs(mProfileLock),mProfileSvc,mNativeApp,&mStartOffline,&mProfileName);if(rv==NS_ERROR_LAUNCHED_CHILD_PROCESS||rv==NS_ERROR_ABORT){*aExitFlag=true;return0;}if(NS_FAILED(rv)){// We failed to choose or create profile - notify user and quitProfileMissingDialog(mNativeApp);return1;}gProfileLock=mProfileLock;rv=mProfileLock->GetDirectory(getter_AddRefs(mProfD));NS_ENSURE_SUCCESS(rv,1);rv=mProfileLock->GetLocalDirectory(getter_AddRefs(mProfLD));NS_ENSURE_SUCCESS(rv,1);nsAutoCStringversion;BuildVersion(version);#ifdef TARGET_OS_ABINS_NAMED_LITERAL_CSTRING(osABI,TARGET_OS_ABI);#else// No TARGET_XPCOM_ABI, but at least the OS is knownNS_NAMED_LITERAL_CSTRING(osABI,OS_TARGET"_UNKNOWN");#endif// Check for version compatibility with the last version of the app this// profile was started with. The format of the version stamp is defined// by the BuildVersion function.// Also check to see if something has happened to invalidate our// fastload caches, like an extension upgrade or installation.// If we see .purgecaches, that means someone did a make.// Re-register components to catch potential changes.nsCOMPtr<nsIFile>flagFile;if(mAppData->directory){Unused<<mAppData->directory->Clone(getter_AddRefs(flagFile));}if(flagFile){flagFile->AppendNative(FILE_INVALIDATE_CACHES);}boolcachesOK;boolisDowngrade;nsCStringlastVersion;boolversionOK=CheckCompatibility(mProfD,version,osABI,mDirProvider.GetGREDir(),mAppData->directory,flagFile,&cachesOK,&isDowngrade,lastVersion);#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE// The argument check must come first so the argument is always removed from// the command line regardless of whether this is a downgrade or not.if(!CheckArg("allow-downgrade")&&isDowngrade){rv=CheckDowngrade(mProfD,mProfLD,mProfileName,mNativeApp,mProfileSvc,lastVersion);if(rv==NS_ERROR_LAUNCHED_CHILD_PROCESS||rv==NS_ERROR_ABORT){*aExitFlag=true;return0;}}#endifrv=mDirProvider.SetProfile(mProfD,mProfLD);NS_ENSURE_SUCCESS(rv,1);//////////////////////// NOW WE HAVE A PROFILE ////////////////////////mozilla::Telemetry::SetProfileDir(mProfD);if(mAppData->flags&NS_XRE_ENABLE_CRASH_REPORTER){MakeOrSetMinidumpPath(mProfD);}CrashReporter::SetProfileDirectory(mProfD);#ifdef MOZ_ASAN_REPORTER// In ASan reporter builds, we need to set ASan's log_path as early as// possible, so it dumps its errors into files there instead of using// the default stderr location. Since this is crucial for ASan reporter// to work at all (and we don't want people to use a non-functional// ASan reporter build), all failures while setting log_path are fatal.setASanReporterPath(mProfD);// Export to env for child processesSaveFileToEnv("ASAN_REPORTER_PATH",mProfD);#endifboollastStartupWasCrash=CheckLastStartupWasCrash().unwrapOr(false);if(CheckArg("purgecaches")||PR_GetEnv("MOZ_PURGE_CACHES")||lastStartupWasCrash){cachesOK=false;}// Every time a profile is loaded by a build with a different version,// it updates the compatibility.ini file saying what version last wrote// the fastload caches. On subsequent launches if the version matches,// there is no need for re-registration. If the user loads the same// profile in different builds the component registry must be// re-generated to prevent mysterious component loading failures.//boolstartupCacheValid=true;if(gSafeMode){startupCacheValid=RemoveComponentRegistries(mProfD,mProfLD,false);WriteVersion(mProfD,NS_LITERAL_CSTRING("Safe Mode"),osABI,mDirProvider.GetGREDir(),mAppData->directory,!startupCacheValid);}elseif(versionOK){if(!cachesOK){// Remove caches, forcing component re-registration.// The new list of additional components directories is derived from// information in "extensions.ini".startupCacheValid=RemoveComponentRegistries(mProfD,mProfLD,false);// Rewrite compatibility.ini to remove the flagWriteVersion(mProfD,version,osABI,mDirProvider.GetGREDir(),mAppData->directory,!startupCacheValid);}// Nothing need be done for the normal startup case.}else{// Remove caches, forcing component re-registration// with the default set of components (this disables any potentially// troublesome incompatible XPCOM components).startupCacheValid=RemoveComponentRegistries(mProfD,mProfLD,true);// Write out versionWriteVersion(mProfD,version,osABI,mDirProvider.GetGREDir(),mAppData->directory,!startupCacheValid);}if(!startupCacheValid)StartupCache::IgnoreDiskCache();if(flagFile){flagFile->Remove(true);}return0;}#if defined(MOZ_CONTENT_SANDBOX)voidAddSandboxAnnotations(){// Include the sandbox content level, regardless of platformintlevel=GetEffectiveContentSandboxLevel();nsAutoCStringlevelString;levelString.AppendInt(level);CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::ContentSandboxLevel,levelString);// Include whether or not this instance is capable of content sandboxingboolsandboxCapable=false;# if defined(XP_WIN)// All supported Windows versions support some level of content sandboxingsandboxCapable=true;# elif defined(XP_MACOSX)// All supported OS X versions are capablesandboxCapable=true;# elif defined(XP_LINUX)sandboxCapable=SandboxInfo::Get().CanSandboxContent();# elif defined(__OpenBSD__)sandboxCapable=true;StartOpenBSDSandbox(GeckoProcessType_Default);# endifCrashReporter::AnnotateCrashReport(CrashReporter::Annotation::ContentSandboxCapable,sandboxCapable);}#endif /* MOZ_CONTENT_SANDBOX *//* * XRE_mainRun - Command line startup, profile migration, and * the calling of appStartup->Run(). */nsresultXREMain::XRE_mainRun(){nsresultrv=NS_OK;NS_ASSERTION(mScopedXPCOM,"Scoped xpcom not initialized.");#if defined(XP_WIN)RefPtr<mozilla::DllServices>dllServices(mozilla::DllServices::Get());autodllServicesDisable=MakeScopeExit([&dllServices](){dllServices->Disable();});#endif // defined(XP_WIN)#ifdef NS_FUNCTION_TIMER// initialize some common services, so we don't pay the cost for these at odd// times later on; SetWindowCreator -> ChromeRegistry -> IOService ->// SocketTransportService -> (nspr wspm init), Prefs{nsCOMPtr<nsISupports>comp;comp=do_GetService("@mozilla.org/preferences-service;1");comp=do_GetService("@mozilla.org/network/socket-transport-service;1");comp=do_GetService("@mozilla.org/network/dns-service;1");comp=do_GetService("@mozilla.org/network/io-service;1");comp=do_GetService("@mozilla.org/chrome/chrome-registry;1");comp=do_GetService("@mozilla.org/focus-event-suppressor-service;1");}#endifrv=mScopedXPCOM->SetWindowCreator(mNativeApp);NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);// tell the crash reporter to also send the release channelnsCOMPtr<nsIPrefService>prefs=do_GetService("@mozilla.org/preferences-service;1",&rv);if(NS_SUCCEEDED(rv)){nsCOMPtr<nsIPrefBranch>defaultPrefBranch;rv=prefs->GetDefaultBranch(nullptr,getter_AddRefs(defaultPrefBranch));if(NS_SUCCEEDED(rv)){nsAutoCStringsval;rv=defaultPrefBranch->GetCharPref("app.update.channel",sval);if(NS_SUCCEEDED(rv)){CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::ReleaseChannel,sval);}}}// Needs to be set after xpcom initialization.CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::FramePoisonBase,nsPrintfCString("%.16"PRIu64,uint64_t(gMozillaPoisonBase)));CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::FramePoisonSize,uint32_t(gMozillaPoisonSize));boolincludeContextHeap=Preferences::GetBool("toolkit.crashreporter.include_context_heap",false);CrashReporter::SetIncludeContextHeap(includeContextHeap);#ifdef XP_WINPR_CreateThread(PR_USER_THREAD,AnnotateWMIData_ThreadStart,0,PR_PRIORITY_LOW,PR_GLOBAL_THREAD,PR_UNJOINABLE_THREAD,0);#endif#if defined(XP_LINUX) && !defined(ANDROID)PR_CreateThread(PR_USER_THREAD,AnnotateLSBRelease,0,PR_PRIORITY_LOW,PR_GLOBAL_THREAD,PR_UNJOINABLE_THREAD,0);#endifif(mStartOffline){nsCOMPtr<nsIIOService>io(do_GetService("@mozilla.org/network/io-service;1"));NS_ENSURE_TRUE(io,NS_ERROR_FAILURE);io->SetManageOfflineStatus(false);io->SetOffline(true);}#ifdef XP_WINif(!PR_GetEnv("XRE_NO_DLL_READAHEAD")){PR_CreateThread(PR_USER_THREAD,ReadAheadDlls_ThreadStart,0,PR_PRIORITY_NORMAL,PR_GLOBAL_THREAD,PR_UNJOINABLE_THREAD,0);}#endifif(gDoMigration){nsCOMPtr<nsIFile>file;mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));file->AppendNative(NS_LITERAL_CSTRING("override.ini"));nsINIParserparser;nsresultrv=parser.Init(file);// if override.ini doesn't exist, also check for distribution.iniif(NS_FAILED(rv)){boolpersistent;mDirProvider.GetFile(XRE_APP_DISTRIBUTION_DIR,&persistent,getter_AddRefs(file));file->AppendNative(NS_LITERAL_CSTRING("distribution.ini"));rv=parser.Init(file);}if(NS_SUCCEEDED(rv)){nsAutoCStringbuf;rv=parser.GetString("XRE","EnableProfileMigrator",buf);if(NS_SUCCEEDED(rv)){if(buf[0]=='0'||buf[0]=='f'||buf[0]=='F'){gDoMigration=false;}}}}{// Profile Migrationif(mAppData->flags&NS_XRE_ENABLE_PROFILE_MIGRATOR&&gDoMigration){gDoMigration=false;nsCOMPtr<nsIProfileMigrator>pm(do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID));if(pm){nsAutoCStringaKey;nsAutoCStringaName;if(gDoProfileReset){// Automatically migrate from the current application if we just// reset the profile.aKey=MOZ_APP_NAME;gResetOldProfile->GetName(aName);}pm->Migrate(&mDirProvider,aKey,aName);}}if(gDoProfileReset){nsresultbackupCreated=ProfileResetCleanup(static_cast<nsToolkitProfileService*>(mProfileSvc.get()),gResetOldProfile);if(NS_FAILED(backupCreated))NS_WARNING("Could not cleanup the profile that was reset");}}#ifndef XP_WINnsCOMPtr<nsIFile>profileDir;nsAutoCStringpath;rv=mDirProvider.GetProfileStartupDir(getter_AddRefs(profileDir));if(NS_SUCCEEDED(rv)&&NS_SUCCEEDED(profileDir->GetNativePath(path))&&!IsUTF8(path)){PR_fprintf(PR_STDERR,"Error: The profile path is not valid UTF-8. Unable to continue.\n");returnNS_ERROR_FAILURE;}#endif// Initialize user preferences before notifying startup observers so they're// ready in time for early consumers, such as the component loader.mDirProvider.InitializeUserPrefs();nsAppStartupNotifier::NotifyObservers(APPSTARTUP_TOPIC);nsCOMPtr<nsIAppStartup>appStartup(components::AppStartup::Service());NS_ENSURE_TRUE(appStartup,NS_ERROR_FAILURE);mDirProvider.DoStartup();// As FilePreferences need the profile directory, we must initialize right// here.mozilla::FilePreferences::InitDirectoriesWhitelist();mozilla::FilePreferences::InitPrefs();OverrideDefaultLocaleIfNeeded();nsCStringuserAgentLocale;LocaleService::GetInstance()->GetAppLocaleAsLangTag(userAgentLocale);CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::useragent_locale,userAgentLocale);appStartup->GetShuttingDown(&mShuttingDown);nsCOMPtr<nsICommandLineRunner>cmdLine;nsCOMPtr<nsIFile>workingDir;rv=NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR,getter_AddRefs(workingDir));NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);if(!mShuttingDown){cmdLine=newnsCommandLine();rv=cmdLine->Init(gArgc,gArgv,workingDir,nsICommandLine::STATE_INITIAL_LAUNCH);NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);/* Special-case services that need early access to the command line. */nsCOMPtr<nsIObserverService>obsService=mozilla::services::GetObserverService();if(obsService){obsService->NotifyObservers(cmdLine,"command-line-startup",nullptr);}}#ifdef XP_WIN// Hack to sync up the various environment storages. XUL_APP_FILE is special// in that it comes from a different CRT (firefox.exe's static-linked copy).// Ugly details in http://bugzil.la/1175039#c27charappFile[MAX_PATH];if(GetEnvironmentVariableA("XUL_APP_FILE",appFile,sizeof(appFile))){SmprintfPointersaved=mozilla::Smprintf("XUL_APP_FILE=%s",appFile);// We intentionally leak the string here since it is required by PR_SetEnv.PR_SetEnv(saved.release());}#endifSaveStateForAppInitiatedRestart();// clear out any environment variables which may have been set// during the relaunch process now that we know we won't be relaunching.SaveToEnv("XRE_PROFILE_PATH=");SaveToEnv("XRE_PROFILE_LOCAL_PATH=");SaveToEnv("XRE_START_OFFLINE=");SaveToEnv("XUL_APP_FILE=");SaveToEnv("XRE_BINARY_PATH=");SaveToEnv("XRE_RESTARTED_BY_PROFILE_MANAGER=");if(!mShuttingDown){rv=appStartup->CreateHiddenWindow();NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);#ifdef XP_WINPreferences::RegisterCallbackAndCall(RegisterApplicationRestartChanged,PREF_WIN_REGISTER_APPLICATION_RESTART);# if defined(MOZ_LAUNCHER_PROCESS)SetupLauncherProcessPref();# endif // defined(MOZ_LAUNCHER_PROCESS)#endif#if defined(HAVE_DESKTOP_STARTUP_ID) && defined(MOZ_WIDGET_GTK)nsGTKToolkit*toolkit=nsGTKToolkit::GetToolkit();if(toolkit&&!mDesktopStartupID.IsEmpty()){toolkit->SetDesktopStartupID(mDesktopStartupID);}// Clear the environment variable so it won't be inherited by// child processes and confuse things.g_unsetenv("DESKTOP_STARTUP_ID");#endif#ifdef XP_MACOSX// we re-initialize the command-line service and do appleevents munging// after we are sure that we're not restartingcmdLine=newnsCommandLine();CommandLineServiceMac::SetupMacCommandLine(gArgc,gArgv,false);rv=cmdLine->Init(gArgc,gArgv,workingDir,nsICommandLine::STATE_INITIAL_LAUNCH);NS_ENSURE_SUCCESS(rv,NS_ERROR_FAILURE);#endifnsCOMPtr<nsIObserverService>obsService=mozilla::services::GetObserverService();if(obsService)obsService->NotifyObservers(nullptr,"final-ui-startup",nullptr);(void)appStartup->DoneStartingUp();CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::StartupCrash,false);appStartup->GetShuttingDown(&mShuttingDown);}if(!mShuttingDown){rv=cmdLine->Run();NS_ENSURE_SUCCESS_LOG(rv,NS_ERROR_FAILURE);appStartup->GetShuttingDown(&mShuttingDown);}if(!mShuttingDown){#if defined(MOZ_WIDGET_GTK)// if we have X remote support, start listening for requests on the// proxy window.if(!mDisableRemote)mRemoteService=do_GetService("@mozilla.org/toolkit/remote-service;1");if(mRemoteService)mRemoteService->Startup(mAppData->remotingName,mProfileName.get());if(mRemoteLockDir){mRemoteLock.Unlock();mRemoteLock.Cleanup();mRemoteLockDir->Remove(false);}#endif /* MOZ_WIDGET_GTK */mNativeApp->Enable();}#ifdef MOZ_INSTRUMENT_EVENT_LOOPif(PR_GetEnv("MOZ_INSTRUMENT_EVENT_LOOP")){boollogToConsole=true;mozilla::InitEventTracing(logToConsole);}#endif /* MOZ_INSTRUMENT_EVENT_LOOP */#if defined(MOZ_SANDBOX) && defined(XP_LINUX)// If we're on Linux, we now have information about the OS capabilities// available to us.SandboxInfosandboxInfo=SandboxInfo::Get();Telemetry::Accumulate(Telemetry::SANDBOX_HAS_SECCOMP_BPF,sandboxInfo.Test(SandboxInfo::kHasSeccompBPF));Telemetry::Accumulate(Telemetry::SANDBOX_HAS_SECCOMP_TSYNC,sandboxInfo.Test(SandboxInfo::kHasSeccompTSync));Telemetry::Accumulate(Telemetry::SANDBOX_HAS_USER_NAMESPACES_PRIVILEGED,sandboxInfo.Test(SandboxInfo::kHasPrivilegedUserNamespaces));Telemetry::Accumulate(Telemetry::SANDBOX_HAS_USER_NAMESPACES,sandboxInfo.Test(SandboxInfo::kHasUserNamespaces));Telemetry::Accumulate(Telemetry::SANDBOX_CONTENT_ENABLED,sandboxInfo.Test(SandboxInfo::kEnabledForContent));Telemetry::Accumulate(Telemetry::SANDBOX_MEDIA_ENABLED,sandboxInfo.Test(SandboxInfo::kEnabledForMedia));nsAutoCStringflagsString;flagsString.AppendInt(sandboxInfo.AsInteger());CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::ContentSandboxCapabilities,flagsString);#endif /* MOZ_SANDBOX && XP_LINUX */#if defined(MOZ_CONTENT_SANDBOX)AddSandboxAnnotations();#endif /* MOZ_CONTENT_SANDBOX */static_cast<nsToolkitProfileService*>(mProfileSvc.get())->CompleteStartup();{rv=appStartup->Run();if(NS_FAILED(rv)){NS_ERROR("failed to run appstartup");gLogConsoleErrors=true;}}returnrv;}/* * XRE_main - A class based main entry point used by most platforms. * Note that on OSX, aAppData->xreDirectory will point to * .app/Contents/Resources. */intXREMain::XRE_main(intargc,char*argv[],constBootstrapConfig&aConfig){ScopedLogginglog;mozilla::LogModule::Init(argc,argv);#ifdef MOZ_CODE_COVERAGECodeCoverageHandler::Init();#endifAUTO_PROFILER_INIT;AUTO_PROFILER_LABEL("XREMain::XRE_main",OTHER);nsresultrv=NS_OK;gArgc=argc;gArgv=argv;if(aConfig.appData){mAppData=MakeUnique<XREAppData>(*aConfig.appData);}else{MOZ_RELEASE_ASSERT(aConfig.appDataPath);nsCOMPtr<nsIFile>appini;rv=XRE_GetFileFromPath(aConfig.appDataPath,getter_AddRefs(appini));if(NS_FAILED(rv)){Output(true,"Error: unrecognized path: %s\n",aConfig.appDataPath);return1;}mAppData=MakeUnique<XREAppData>();rv=XRE_ParseAppData(appini,*mAppData);if(NS_FAILED(rv)){Output(true,"Couldn't read application.ini");return1;}appini->GetParent(getter_AddRefs(mAppData->directory));}if(!mAppData->remotingName){mAppData->remotingName=mAppData->name;}// used throughout this filegAppData=mAppData.get();nsCOMPtr<nsIFile>binFile;rv=XRE_GetBinaryPath(getter_AddRefs(binFile));NS_ENSURE_SUCCESS(rv,1);rv=binFile->GetPath(gAbsoluteArgv0Path);NS_ENSURE_SUCCESS(rv,1);if(!mAppData->xreDirectory){nsCOMPtr<nsIFile>lf;rv=XRE_GetBinaryPath(getter_AddRefs(lf));if(NS_FAILED(rv))return2;nsCOMPtr<nsIFile>greDir;rv=lf->GetParent(getter_AddRefs(greDir));if(NS_FAILED(rv))return2;#ifdef XP_MACOSXnsCOMPtr<nsIFile>parent;greDir->GetParent(getter_AddRefs(parent));greDir=parent.forget();greDir->AppendNative(NS_LITERAL_CSTRING("Resources"));#endifmAppData->xreDirectory=greDir;}if(aConfig.appData&&aConfig.appDataPath){mAppData->xreDirectory->Clone(getter_AddRefs(mAppData->directory));mAppData->directory->AppendNative(nsDependentCString(aConfig.appDataPath));}if(!mAppData->directory){mAppData->directory=mAppData->xreDirectory;}#if defined(XP_WIN) && defined(MOZ_SANDBOX)mAppData->sandboxBrokerServices=aConfig.sandboxBrokerServices;mAppData->sandboxPermissionsService=aConfig.sandboxPermissionsService;#endifmozilla::IOInterposerInitioInterposerGuard;#if defined(XP_WIN)// Some COM settings are global to the process and must be set before any non-// trivial COM is run in the application. Since these settings may affect// stability, we should instantiate COM ASAP so that we can ensure that these// global settings are configured before anything can interfere.mozilla::mscom::MainThreadRuntimemsCOMRuntime;#endif// initboolexit=false;intresult=XRE_mainInit(&exit);if(result!=0||exit)returnresult;// If we exit gracefully, remove the startup crash canary file.autocleanup=MakeScopeExit([&]()->nsresult{if(mProfLD){nsCOMPtr<nsIFile>crashFile;MOZ_TRY_VAR(crashFile,GetIncompleteStartupFile(mProfLD));crashFile->Remove(false);}returnNS_OK;});// startupresult=XRE_mainStartup(&exit);if(result!=0||exit)returnresult;boolappInitiatedRestart=false;// Start the real applicationmScopedXPCOM=MakeUnique<ScopedXPCOMStartup>();if(!mScopedXPCOM)return1;rv=mScopedXPCOM->Initialize();NS_ENSURE_SUCCESS(rv,1);// run!rv=XRE_mainRun();#ifdef MOZ_INSTRUMENT_EVENT_LOOPmozilla::ShutdownEventTracing();#endifgAbsoluteArgv0Path.Truncate();// Check for an application initiated restart. This is one that// corresponds to nsIAppStartup.quit(eRestart)if(rv==NS_SUCCESS_RESTART_APP||rv==NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE){appInitiatedRestart=true;// We have an application restart don't do any shutdown checks here// In particular we don't want to poison IO for checking late-writes.gShutdownChecks=SCM_NOTHING;}if(!mShuttingDown){#if defined(MOZ_WIDGET_GTK)// shut down the x remote proxy windowif(mRemoteService){mRemoteService->Shutdown();}#endif /* MOZ_WIDGET_GTK */}mScopedXPCOM=nullptr;#if defined(XP_WIN)mozilla::widget::StopAudioSession();#endif// unlock the profile after ScopedXPCOMStartup object (xpcom)// has gone out of scope. see bug #386739 for more detailsmProfileLock->Unlock();gProfileLock=nullptr;// Restart the app after XPCOM has been shut down cleanly.if(appInitiatedRestart){RestoreStateForAppInitiatedRestart();if(rv!=NS_SUCCESS_RESTART_APP_NOT_SAME_PROFILE){// Ensure that these environment variables are set:SaveFileToEnvIfUnset("XRE_PROFILE_PATH",mProfD);SaveFileToEnvIfUnset("XRE_PROFILE_LOCAL_PATH",mProfLD);}#ifdef MOZ_WIDGET_GTKif(!gfxPlatform::IsHeadless()){MOZ_gdk_display_close(mGdkDisplay);}#endif{rv=LaunchChild(mNativeApp,true);}if(mAppData->flags&NS_XRE_ENABLE_CRASH_REPORTER)CrashReporter::UnsetExceptionHandler();returnrv==NS_ERROR_LAUNCHED_CHILD_PROCESS?0:1;}#ifdef MOZ_WIDGET_GTK// gdk_display_close also calls gdk_display_manager_set_default_display// appropriately when necessary.if(!gfxPlatform::IsHeadless()){MOZ_gdk_display_close(mGdkDisplay);}#endifif(mAppData->flags&NS_XRE_ENABLE_CRASH_REPORTER)CrashReporter::UnsetExceptionHandler();XRE_DeinitCommandLine();returnNS_FAILED(rv)?1:0;}voidXRE_StopLateWriteChecks(void){mozilla::StopLateWriteChecks();}intXRE_main(intargc,char*argv[],constBootstrapConfig&aConfig){XREMainmain;intresult=main.XRE_main(argc,argv,aConfig);mozilla::RecordShutdownEndTimeStamp();returnresult;}nsresultXRE_InitCommandLine(intaArgc,char*aArgv[]){nsresultrv=NS_OK;#if defined(OS_WIN)CommandLine::Init(aArgc,aArgv);#else// these leak on error, but that's OK: we'll just exit()char**canonArgs=newchar*[aArgc];// get the canonical version of the binary's pathnsCOMPtr<nsIFile>binFile;rv=XRE_GetBinaryPath(getter_AddRefs(binFile));if(NS_FAILED(rv))returnNS_ERROR_FAILURE;nsAutoCStringcanonBinPath;rv=binFile->GetNativePath(canonBinPath);if(NS_FAILED(rv))returnNS_ERROR_FAILURE;canonArgs[0]=strdup(canonBinPath.get());for(inti=1;i<aArgc;++i){if(aArgv[i]){canonArgs[i]=strdup(aArgv[i]);}}NS_ASSERTION(!CommandLine::IsInitialized(),"Bad news!");CommandLine::Init(aArgc,canonArgs);for(inti=0;i<aArgc;++i)free(canonArgs[i]);delete[]canonArgs;#endifrecordreplay::parent::InitializeUIProcess(gArgc,gArgv);constchar*path=nullptr;ArgResultar=CheckArg("greomni",&path);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --greomni requires a path argument\n");returnNS_ERROR_FAILURE;}if(!path)returnrv;nsCOMPtr<nsIFile>greOmni;rv=XRE_GetFileFromPath(path,getter_AddRefs(greOmni));if(NS_FAILED(rv)){PR_fprintf(PR_STDERR,"Error: argument --greomni requires a valid path\n");returnrv;}ar=CheckArg("appomni",&path);if(ar==ARG_BAD){PR_fprintf(PR_STDERR,"Error: argument --appomni requires a path argument\n");returnNS_ERROR_FAILURE;}nsCOMPtr<nsIFile>appOmni;if(path){rv=XRE_GetFileFromPath(path,getter_AddRefs(appOmni));if(NS_FAILED(rv)){PR_fprintf(PR_STDERR,"Error: argument --appomni requires a valid path\n");returnrv;}}mozilla::Omnijar::Init(greOmni,appOmni);returnrv;}nsresultXRE_DeinitCommandLine(){nsresultrv=NS_OK;CommandLine::Terminate();returnrv;}GeckoProcessTypeXRE_GetProcessType(){returnmozilla::startup::sChildProcessType;}boolXRE_IsE10sParentProcess(){returnXRE_IsParentProcess()&&BrowserTabsRemoteAutostart();}#define GECKO_PROCESS_TYPE(enum_name, string_name, xre_name) \ bool XRE_Is##xre_name##Process() { \ return XRE_GetProcessType() == GeckoProcessType_##enum_name; \ }#include"mozilla/GeckoProcessTypes.h"#undef GECKO_PROCESS_TYPEboolXRE_UseNativeEventProcessing(){#if defined(XP_MACOSX) || defined(XP_WIN)if(XRE_IsRDDProcess()||XRE_IsSocketProcess()){returnfalse;}#endifif(XRE_IsContentProcess()){staticboolsInited=false;staticboolsUseNativeEventProcessing=false;if(!sInited){Preferences::AddBoolVarCache(&sUseNativeEventProcessing,"dom.ipc.useNativeEventProcessing.content");sInited=true;}returnsUseNativeEventProcessing;}returntrue;}#if defined(XP_WIN)boolXRE_Win32kCallsAllowed(){switch(XRE_GetProcessType()){caseGeckoProcessType_GMPlugin:caseGeckoProcessType_RDD:returnfalse;default:returntrue;}}#endif// If you add anything to this enum, please update about:support to reflect itenum{kE10sEnabledByUser=0,kE10sEnabledByDefault=1,kE10sDisabledByUser=2,// kE10sDisabledInSafeMode = 3, was removed in bug 1172491.// kE10sDisabledForAccessibility = 4,// kE10sDisabledForMacGfx = 5, was removed in bug 1068674.// kE10sDisabledForBidi = 6, removed in bug 1309599// kE10sDisabledForAddons = 7, removed in bug 1406212kE10sForceDisabled=8,// kE10sDisabledForXPAcceleration = 9, removed in bug 1296353// kE10sDisabledForOperatingSystem = 10, removed due to xp-eol};constchar*kForceEnableE10sPref="browser.tabs.remote.force-enable";constchar*kForceDisableE10sPref="browser.tabs.remote.force-disable";namespacemozilla{boolBrowserTabsRemoteAutostart(){if(gBrowserTabsRemoteAutostartInitialized){returngBrowserTabsRemoteAutostart;}gBrowserTabsRemoteAutostartInitialized=true;// If we're in the content process, we are running E10S.if(XRE_IsContentProcess()){gBrowserTabsRemoteAutostart=true;returngBrowserTabsRemoteAutostart;}booloptInPref=Preferences::GetBool("browser.tabs.remote.autostart",true);intstatus=kE10sEnabledByDefault;if(optInPref){gBrowserTabsRemoteAutostart=true;}else{status=kE10sDisabledByUser;}// Uber override pref for manual testing purposesif(Preferences::GetBool(kForceEnableE10sPref,false)){gBrowserTabsRemoteAutostart=true;status=kE10sEnabledByUser;}// Uber override pref for emergency blockingif(gBrowserTabsRemoteAutostart&&(Preferences::GetBool(kForceDisableE10sPref,false)||EnvHasValue("MOZ_FORCE_DISABLE_E10S"))){gBrowserTabsRemoteAutostart=false;status=kE10sForceDisabled;}gBrowserTabsRemoteStatus=status;returngBrowserTabsRemoteAutostart;}uint32_tGetMaxWebProcessCount(){// multiOptOut is in int to allow us to run multiple experiments without// introducing multiple prefs a la the autostart.N prefs.if(Preferences::GetInt("dom.ipc.multiOptOut",0)>=nsIXULRuntime::E10S_MULTI_EXPERIMENT){return1;}constchar*optInPref="dom.ipc.processCount";uint32_toptInPrefValue=Preferences::GetInt(optInPref,1);returnstd::max(1u,optInPrefValue);}constchar*PlatformBuildID(){returngToolkitBuildID;}}// namespace mozillavoidSetupErrorHandling(constchar*progname){#ifdef XP_WIN/* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default we still want DEP protection: enable it explicitly and programmatically. This function is not available on WinXPSP2 so we dynamically load it. */HMODULEkernel32=GetModuleHandleW(L"kernel32.dll");SetProcessDEPPolicyFunc_SetProcessDEPPolicy=(SetProcessDEPPolicyFunc)GetProcAddress(kernel32,"SetProcessDEPPolicy");if(_SetProcessDEPPolicy)_SetProcessDEPPolicy(PROCESS_DEP_ENABLE);#endif#ifdef XP_WIN32// Suppress the "DLL Foo could not be found" dialog, such that if dependent// libraries (such as GDI+) are not preset, we gracefully fail to load those// XPCOM components, instead of being ungraceful.UINTrealMode=SetErrorMode(0);realMode|=SEM_FAILCRITICALERRORS;// If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This// application has crashed" dialog box. This is mainly useful for// automated testing environments, e.g. tinderbox, where there's no need// for a dozen of the dialog boxes to litter the consoleif(getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))realMode|=SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX;SetErrorMode(realMode);#endifInstallSignalHandlers(progname);// Unbuffer stdout, needed for tinderbox tests.setbuf(stdout,0);}// Note: This function should not be needed anymore. See Bug 818634 for details.voidOverrideDefaultLocaleIfNeeded(){// Read pref to decide whether to override default locale with US English.if(mozilla::Preferences::GetBool("javascript.use_us_english_locale",false)){// Set the application-wide C-locale. Needed to resist fingerprinting// of Date.toLocaleFormat(). We use the locale to "C.UTF-8" if possible,// to avoid interfering with non-ASCII keyboard input on some Linux// desktops. Otherwise fall back to the "C" locale, which is available on// all platforms.setlocale(LC_ALL,"C.UTF-8")||setlocale(LC_ALL,"C");}}voidXRE_EnableSameExecutableForContentProc(){if(!PR_GetEnv("MOZ_SEPARATE_CHILD_PROCESS")){mozilla::ipc::GeckoChildProcessHost::EnableSameExecutableForContentProc();}}// Because rust doesn't handle weak symbols, this function wraps the weak// malloc_handle_oom for it.extern"C"voidGeckoHandleOOM(size_tsize){mozalloc_handle_oom(size);}// Similarly, this wraps MOZ_Crashextern"C"voidGeckoCrash(constchar*aFilename,intaLine,constchar*aReason){MOZ_Crash(aFilename,aLine,aReason);}// From toolkit/library/rust/shared/lib.rsextern"C"voidinstall_rust_panic_hook();extern"C"voidinstall_rust_oom_hook();structInstallRustHooks{InstallRustHooks(){install_rust_panic_hook();install_rust_oom_hook();}};InstallRustHookssInstallRustHooks;#ifdef MOZ_ASAN_REPORTERvoidsetASanReporterPath(nsIFile*aDir){nsCOMPtr<nsIFile>dir;aDir->Clone(getter_AddRefs(dir));dir->Append(NS_LITERAL_STRING("asan"));nsresultrv=dir->Create(nsIFile::DIRECTORY_TYPE,0700);if(NS_WARN_IF(NS_FAILED(rv)&&rv!=NS_ERROR_FILE_ALREADY_EXISTS)){MOZ_CRASH("[ASan Reporter] Unable to create crash directory.");}dir->Append(NS_LITERAL_STRING("ff_asan_log"));# ifdef XP_WINnsAutoStringnspathW;rv=dir->GetPath(nspathW);NS_ConvertUTF16toUTF8nspath(nspathW);# elsensAutoCStringnspath;rv=dir->GetNativePath(nspath);# endifif(NS_FAILED(rv)){MOZ_CRASH("[ASan Reporter] Unable to get native path for crash directory.");}__sanitizer_set_report_path(nspath.get());}#endif