Source code

Revision control

Other Tools

/* -*- 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/AppShutdown.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/StaticPrefs_fission.h"
#include "mozilla/Telemetry.h"
#include "mozilla/Utf8.h"
#include "mozilla/intl/LocaleService.h"
#include "mozilla/JSONWriter.h"
#include "BaseProfiler.h"
#include "nsAppRunner.h"
#include "mozilla/XREAppData.h"
#include "mozilla/Bootstrap.h"
#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
# include "nsUpdateDriver.h"
# include "nsUpdateSyncManager.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 "nsIAppStartup.h"
#include "nsAppStartupNotifier.h"
#include "nsIMutableArray.h"
#include "nsCommandLine.h"
#include "nsIComponentRegistrar.h"
#include "nsIDialogParamBlock.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 "nsIToolkitProfile.h"
#include "nsIUUIDGenerator.h"
#include "nsToolkitProfileService.h"
#include "nsIURI.h"
#include "nsIURL.h"
#include "nsIWindowCreator.h"
#include "nsIWindowWatcher.h"
#include "nsIXULAppInfo.h"
#include "nsIXULRuntime.h"
#include "nsPIDOMWindow.h"
#include "nsIWidget.h"
#include "nsAppShellCID.h"
#include "mozilla/dom/quota/QuotaManager.h"
#include "mozilla/scache/StartupCache.h"
#include "gfxPlatform.h"
#ifdef XP_MACOSX
# include "gfxPlatformMac.h"
#endif
#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/PreXULSkeletonUI.h"
# include "mozilla/DllPrefetchExperimentRegistryInfo.h"
# include "mozilla/WindowsDllBlocklist.h"
# include "mozilla/WindowsProcessMitigations.h"
# include "mozilla/WinHeaderOnlyUtils.h"
# include "mozilla/mscom/ProcessRuntime.h"
# include "mozilla/mscom/ProfilerMarkers.h"
# include "mozilla/widget/AudioSession.h"
# include "WinTokenUtils.h"
# if defined(MOZ_LAUNCHER_PROCESS)
# include "mozilla/LauncherRegistryInfo.h"
# endif
# if defined(MOZ_DEFAULT_BROWSER_AGENT)
# include "nsIWindowsRegKey.h"
# endif
# ifndef PROCESS_DEP_ENABLE
# define PROCESS_DEP_ENABLE 0x1
# endif
#endif
#if defined(MOZ_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 "WinUtils.h"
#endif
#ifdef XP_MACOSX
# include "nsILocalFileMac.h"
# include "nsCommandLineServiceMac.h"
#endif
// for X remote support
#if defined(MOZ_HAS_REMOTE)
# include "nsRemoteService.h"
#endif
#if defined(DEBUG) && defined(XP_WIN)
# 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 "mozilla/java/GeckoAppShellWrappers.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 "SafeMode.h"
#ifdef MOZ_BACKGROUNDTASKS
# include "mozilla/BackgroundTasks.h"
# include "nsIPowerManagerService.h"
# include "nsIStringBundle.h"
#endif
extern uint32_t gRestartMode;
extern void InstallSignalHandlers(const char* ProgramName);
#define FILE_COMPATIBILITY_INFO "compatibility.ini"_ns
#define FILE_INVALIDATE_CACHES ".purgecaches"_ns
#define FILE_STARTUP_INCOMPLETE u".startup-incomplete"_ns
#if defined(MOZ_BLOCK_PROFILE_DOWNGRADE) || defined(MOZ_LAUNCHER_PROCESS) || \
defined(MOZ_DEFAULT_BROWSER_AGENT)
static const char kPrefHealthReportUploadEnabled[] =
"datareporting.healthreport.uploadEnabled";
#endif // defined(MOZ_BLOCK_PROFILE_DOWNGRADE) || defined(MOZ_LAUNCHER_PROCESS)
// || defined(MOZ_DEFAULT_BROWSER_AGENT)
#if defined(MOZ_DEFAULT_BROWSER_AGENT)
static const char kPrefDefaultAgentEnabled[] = "default-browser-agent.enabled";
static const char kPrefServicesSettingsServer[] = "services.settings.server";
static const char kPrefSecurityContentSignatureRootHash[] =
"security.content.signature.root_hash";
static const char kPrefSetDefaultBrowserUserChoicePref[] =
"browser.shell.setDefaultBrowserUserChoice";
#endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
#if defined(XP_WIN)
static const char kPrefThemeId[] = "extensions.activeThemeID";
static const char kPrefBrowserStartupBlankWindow[] =
"browser.startup.blankWindow";
static const char kPrefPreXulSkeletonUI[] = "browser.startup.preXulSkeletonUI";
static const char kPrefDrawTabsInTitlebar[] = "browser.tabs.drawInTitlebar";
#endif // defined(XP_WIN)
int gArgc;
char** gArgv;
static const char gToolkitVersion[] = MOZ_STRINGIFY(GRE_MILESTONE);
// The gToolkitBuildID global is defined to MOZ_BUILDID via gen_buildid.py
// in toolkit/library. See related comment in toolkit/library/moz.build.
extern const char gToolkitBuildID[];
static nsIProfileLock* gProfileLock;
#if defined(MOZ_HAS_REMOTE)
static nsRemoteService* gRemoteService;
#endif
int gRestartArgc;
char** gRestartArgv;
// If gRestartedByOS is set, we were automatically restarted by the OS.
bool gRestartedByOS = false;
bool gIsGtest = false;
nsString gAbsoluteArgv0Path;
#if defined(XP_WIN)
nsString gProcessStartupShortcut;
#endif
#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 "mozilla/WidgetUtilsGtk.h"
# include <gtk/gtk.h>
# ifdef MOZ_WAYLAND
# include <gdk/gdkwayland.h>
# include "mozilla/widget/nsWaylandDisplay.h"
# endif
# ifdef MOZ_X11
# include <gdk/gdkx.h>
# endif /* MOZ_X11 */
# include <fontconfig/fontconfig.h>
#endif
#include "BinaryPath.h"
#ifdef MOZ_LINKER
extern "C" MFBT_API bool IsSignalHandlingBroken();
#endif
#ifdef FUZZING
# include "FuzzerRunner.h"
namespace mozilla {
FuzzerRunner* fuzzerRunner = 0;
} // namespace mozilla
# ifdef LIBFUZZER
void XRE_LibFuzzerSetDriver(LibFuzzerDriver aDriver) {
mozilla::fuzzerRunner->setParams(aDriver);
}
# endif
#endif // FUZZING
// Undo X11/X.h's definition of None
#undef None
namespace mozilla {
int (*RunGTest)(int*, char**) = 0;
bool RunningGTest() { return RunGTest; }
} // namespace mozilla
using namespace mozilla;
using namespace mozilla::widget;
using namespace mozilla::startup;
using mozilla::Unused;
using mozilla::dom::ContentChild;
using mozilla::dom::ContentParent;
using mozilla::dom::quota::QuotaManager;
using mozilla::intl::LocaleService;
using mozilla::scache::StartupCache;
// Save the given word to the specified environment variable.
static void MOZ_NEVER_INLINE SaveWordToEnv(const char* name,
const nsACString& 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.
static void SaveFileToEnv(const char* name, nsIFile* file) {
#ifdef XP_WIN
nsAutoString path;
file->GetPath(path);
SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
#else
nsAutoCString path;
file->GetNativePath(path);
SaveWordToEnv(name, path);
#endif
}
static bool gIsExpectedExit = false;
void MozExpectedExit() { 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.
*/
static void UnexpectedExit() {
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.
*/
static MOZ_FORMAT_PRINTF(2, 3) void Output(bool isError, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
#if defined(XP_WIN) && !MOZ_WINCONSOLE
SmprintfPointer msg = mozilla::Vsmprintf(fmt, ap);
if (msg) {
UINT flags = MB_OK;
if (isError)
flags |= MB_ICONERROR;
else
flags |= MB_ICONINFORMATION;
wchar_t wide_msg[1024];
MultiByteToWideChar(CP_ACP, 0, msg.get(), -1, wide_msg,
sizeof(wide_msg) / sizeof(wchar_t));
MessageBoxW(nullptr, wide_msg, L"XULRunner", flags);
}
#else
vfprintf(stderr, fmt, ap);
#endif
va_end(ap);
}
/**
* 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
*/
static ArgResult CheckArg(const char* aArg, const char** aParam = nullptr,
CheckArgFlag aFlags = CheckArgFlag::RemoveArg) {
MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()");
return CheckArg(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.
*/
static ArgResult CheckArgExists(const char* aArg) {
return CheckArg(aArg, nullptr, CheckArgFlag::None);
}
bool gSafeMode = false;
bool gFxREmbedded = false;
// Fission enablement for the current session is determined once, at startup,
// and then remains the same for the duration of the session.
//
// The following factors determine whether or not Fission is enabled for a
// session, in order of precedence:
//
// - Safe mode: In safe mode, Fission is never enabled.
//
// - The MOZ_FORCE_ENABLE_FISSION environment variable: If set to any value,
// Fission will be enabled.
//
// - The 'fission.autostart' preference, if it has been configured by the user.
static const char kPrefFissionAutostart[] = "fission.autostart";
//
// - The fission experiment enrollment status set during the previous run, which
// is controlled by the following preferences:
//
// The current enrollment status as controlled by Normandy. This value is only
// stored in the default preference branch, and is not persisted across
// sessions by the preference service. It therefore isn't available early
// enough at startup, and needs to be synced to a preference in the user
// branch which is persisted across sessions.
static const char kPrefFissionExperimentEnrollmentStatus[] =
"fission.experiment.enrollmentStatus";
//
// The enrollment status to be used at browser startup. This automatically
// synced from the above enrollmentStatus preference whenever the latter is
// changed. It can have any of the values defined in the
// `nsIXULRuntime_ExperimentStatus` enum. Meanings are documented in
// the declaration of `nsIXULRuntime.fissionExperimentStatus`
static const char kPrefFissionExperimentStartupEnrollmentStatus[] =
"fission.experiment.startupEnrollmentStatus";
// The computed FissionAutostart value for the session, read by content
// processes to initialize gFissionAutostart.
//
// This pref is locked, and only configured on the default branch, so should
// never be persisted in a profile.
static const char kPrefFissionAutostartSession[] = "fission.autostart.session";
static nsIXULRuntime::ExperimentStatus gFissionExperimentStatus =
nsIXULRuntime::eExperimentStatusUnenrolled;
static bool gFissionAutostart = false;
static bool gFissionAutostartInitialized = false;
static nsIXULRuntime::FissionDecisionStatus gFissionDecisionStatus;
enum E10sStatus {
kE10sEnabledByDefault,
kE10sDisabledByUser,
kE10sForceDisabled,
};
static bool gBrowserTabsRemoteAutostart = false;
static E10sStatus gBrowserTabsRemoteStatus;
static bool gBrowserTabsRemoteAutostartInitialized = false;
namespace mozilla {
bool BrowserTabsRemoteAutostart() {
if (gBrowserTabsRemoteAutostartInitialized) {
return gBrowserTabsRemoteAutostart;
}
gBrowserTabsRemoteAutostartInitialized = true;
// If we're not in the parent process, we are running E10s.
if (!XRE_IsParentProcess()) {
gBrowserTabsRemoteAutostart = true;
return gBrowserTabsRemoteAutostart;
}
#if defined(MOZILLA_OFFICIAL) && MOZ_BUILD_APP_IS_BROWSER
bool allowSingleProcessOutsideAutomation = false;
#else
bool allowSingleProcessOutsideAutomation = true;
#endif
E10sStatus status = kE10sEnabledByDefault;
// We use "are non-local connections disabled" as a proxy for
// "are we running some kind of automated test". It would be nicer to use
// xpc::IsInAutomation(), but that depends on some prefs being set, which
// they are not in (at least) gtests (where we can't) and xpcshell.
// Long-term, hopefully we can make tests switch to environment variables
// to disable e10s and then we can get rid of this.
if (allowSingleProcessOutsideAutomation ||
xpc::AreNonLocalConnectionsDisabled()) {
bool optInPref =
Preferences::GetBool("browser.tabs.remote.autostart", true);
if (optInPref) {
gBrowserTabsRemoteAutostart = true;
} else {
status = kE10sDisabledByUser;
}
} else {
gBrowserTabsRemoteAutostart = true;
}
// Uber override pref for emergency blocking
if (gBrowserTabsRemoteAutostart) {
const char* forceDisable = PR_GetEnv("MOZ_FORCE_DISABLE_E10S");
#if defined(MOZ_WIDGET_ANDROID)
// We need this for xpcshell on Android
if (forceDisable && *forceDisable) {
#else
// The environment variable must match the application version to apply.
if (forceDisable && gAppData && !strcmp(forceDisable, gAppData->version)) {
#endif
gBrowserTabsRemoteAutostart = false;
status = kE10sForceDisabled;
}
}
gBrowserTabsRemoteStatus = status;
return gBrowserTabsRemoteAutostart;
}
bool FissionExperimentEnrolled() {
MOZ_ASSERT(XRE_IsParentProcess());
return gFissionExperimentStatus == nsIXULRuntime::eExperimentStatusControl ||
gFissionExperimentStatus ==
nsIXULRuntime::eExperimentStatusTreatment ||
gFissionExperimentStatus == nsIXULRuntime::eExperimentStatusRollout;
}
} // namespace mozilla
static void FissionExperimentDisqualify() {
MOZ_ASSERT(XRE_IsParentProcess());
// Setting this pref's user value will be detected by Normandy, causing the
// client to be unenrolled from the experiment.
Preferences::SetUint(kPrefFissionExperimentEnrollmentStatus,
nsIXULRuntime::eExperimentStatusDisqualified);
}
static void OnFissionEnrollmentStatusChanged(const char* aPref, void* aData) {
Preferences::SetUint(
kPrefFissionExperimentStartupEnrollmentStatus,
Preferences::GetUint(kPrefFissionExperimentEnrollmentStatus,
nsIXULRuntime::eExperimentStatusUnenrolled));
}
namespace {
// This observer is notified during `profile-before-change`, and ensures that
// the experiment enrollment status is synced over before the browser shuts
// down, even if it was not modified since FissionAutostart was initialized.
class FissionEnrollmentStatusShutdownObserver final : public nsIObserver {
public:
NS_DECL_ISUPPORTS
NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
const char16_t* aData) override {
MOZ_ASSERT(!strcmp("profile-before-change", aTopic));
OnFissionEnrollmentStatusChanged(kPrefFissionExperimentEnrollmentStatus,
nullptr);
return NS_OK;
}
private:
~FissionEnrollmentStatusShutdownObserver() = default;
};
NS_IMPL_ISUPPORTS(FissionEnrollmentStatusShutdownObserver, nsIObserver)
} // namespace
static void OnFissionAutostartChanged(const char* aPref, void* aData) {
MOZ_ASSERT(FissionExperimentEnrolled());
if (Preferences::HasUserValue(kPrefFissionAutostart)) {
FissionExperimentDisqualify();
}
}
static void EnsureFissionAutostartInitialized() {
if (gFissionAutostartInitialized) {
return;
}
gFissionAutostartInitialized = true;
if (!XRE_IsParentProcess()) {
// This pref is configured for the current session by the parent process.
gFissionAutostart = Preferences::GetBool(kPrefFissionAutostartSession,
false, PrefValueKind::Default);
return;
}
// Initialize the fission experiment, configuring fission.autostart's
// default, before checking other overrides. This allows opting-out of a
// fission experiment through about:preferences or about:config from a
// safemode session.
uint32_t experimentRaw =
Preferences::GetUint(kPrefFissionExperimentStartupEnrollmentStatus,
nsIXULRuntime::eExperimentStatusUnenrolled);
gFissionExperimentStatus =
experimentRaw < nsIXULRuntime::eExperimentStatusCount
? nsIXULRuntime::ExperimentStatus(experimentRaw)
: nsIXULRuntime::eExperimentStatusDisqualified;
// Watch the experiment enrollment status pref to detect experiment
// disqualification, and ensure it is propagated for the next restart.
Preferences::RegisterCallback(&OnFissionEnrollmentStatusChanged,
kPrefFissionExperimentEnrollmentStatus);
if (nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService()) {
nsCOMPtr<nsIObserver> shutdownObserver =
new FissionEnrollmentStatusShutdownObserver();
observerService->AddObserver(shutdownObserver, "profile-before-change",
false);
}
// If the user has overridden an active experiment by setting a user value for
// "fission.autostart", disqualify the user from the experiment.
if (Preferences::HasUserValue(kPrefFissionAutostart) &&
FissionExperimentEnrolled()) {
FissionExperimentDisqualify();
gFissionExperimentStatus = nsIXULRuntime::eExperimentStatusDisqualified;
}
// Configure the default branch for "fission.autostart" based on experiment
// enrollment status.
if (FissionExperimentEnrolled()) {
bool isTreatment =
gFissionExperimentStatus == nsIXULRuntime::eExperimentStatusTreatment ||
gFissionExperimentStatus == nsIXULRuntime::eExperimentStatusRollout;
Preferences::SetBool(kPrefFissionAutostart, isTreatment,
PrefValueKind::Default);
}
if (!BrowserTabsRemoteAutostart()) {
gFissionAutostart = false;
if (gBrowserTabsRemoteStatus == kE10sForceDisabled) {
gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sEnv;
} else {
gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sOther;
}
} else if (gSafeMode) {
gFissionAutostart = false;
gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledBySafeMode;
} else if (EnvHasValue("MOZ_FORCE_ENABLE_FISSION")) {
gFissionAutostart = true;
gFissionDecisionStatus = nsIXULRuntime::eFissionEnabledByEnv;
} else {
// NOTE: This will take into account changes to the default due to
// `InitializeFissionExperimentStatus`.
gFissionAutostart = Preferences::GetBool(kPrefFissionAutostart, false);
if (gFissionExperimentStatus == nsIXULRuntime::eExperimentStatusControl) {
gFissionDecisionStatus = nsIXULRuntime::eFissionExperimentControl;
} else if (gFissionExperimentStatus ==
nsIXULRuntime::eExperimentStatusTreatment) {
gFissionDecisionStatus = nsIXULRuntime::eFissionExperimentTreatment;
} else if (gFissionExperimentStatus ==
nsIXULRuntime::eExperimentStatusRollout) {
gFissionDecisionStatus = nsIXULRuntime::eFissionEnabledByRollout;
} else if (Preferences::HasUserValue(kPrefFissionAutostart)) {
gFissionDecisionStatus = gFissionAutostart
? nsIXULRuntime::eFissionEnabledByUserPref
: nsIXULRuntime::eFissionDisabledByUserPref;
} else {
gFissionDecisionStatus = gFissionAutostart
? nsIXULRuntime::eFissionEnabledByDefault
: nsIXULRuntime::eFissionDisabledByDefault;
}
}
// Content processes cannot run the same logic as we're running in the parent
// process, as the current value of various preferences may have changed
// between launches. Instead, the content process will read the default branch
// of the locked `fission.autostart.session` preference to determine the value
// determined by this method.
Preferences::Unlock(kPrefFissionAutostartSession);
Preferences::ClearUser(kPrefFissionAutostartSession);
Preferences::SetBool(kPrefFissionAutostartSession, gFissionAutostart,
PrefValueKind::Default);
Preferences::Lock(kPrefFissionAutostartSession);
// If we're actively enrolled in the fission experiment, disqualify the user
// from the experiment if the fission pref is modified.
if (FissionExperimentEnrolled()) {
Preferences::RegisterCallback(&OnFissionAutostartChanged,
kPrefFissionAutostart);
}
}
namespace mozilla {
bool FissionAutostart() {
EnsureFissionAutostartInitialized();
return gFissionAutostart;
}
bool SessionHistoryInParent() {
return FissionAutostart() ||
StaticPrefs::
fission_sessionHistoryInParent_AtStartup_DoNotUseDirectly();
}
bool BFCacheInParent() {
return SessionHistoryInParent() &&
StaticPrefs::fission_bfcacheInParent_DoNotUseDirectly();
}
} // namespace mozilla
/**
* The nsXULAppInfo object implements nsIFactory so that it can be its own
* singleton.
*/
class nsXULAppInfo : public nsIXULAppInfo,
#ifdef XP_WIN
public nsIWinAppHelper,
#endif
public nsICrashReporter,
public nsIFinishDumpingCallback,
public nsIXULRuntime
{
public:
constexpr nsXULAppInfo() = default;
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIPLATFORMINFO
NS_DECL_NSIXULAPPINFO
NS_DECL_NSIXULRUNTIME
NS_DECL_NSICRASHREPORTER
NS_DECL_NSIFINISHDUMPINGCALLBACK
#ifdef XP_WIN
NS_DECL_NSIWINAPPHELPER
#endif
};
NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)
NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)
#ifdef XP_WIN
NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)
#endif
NS_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_END
NS_IMETHODIMP_(MozExternalRefCountType)
nsXULAppInfo::AddRef() { return 1; }
NS_IMETHODIMP_(MozExternalRefCountType)
nsXULAppInfo::Release() { return 1; }
NS_IMETHODIMP
nsXULAppInfo::GetVendor(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().vendor;
return NS_OK;
}
aResult.Assign(gAppData->vendor);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetName(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().name;
return NS_OK;
}
#ifdef MOZ_WIDGET_ANDROID
nsCString name = java::GeckoAppShell::GetAppName()->ToCString();
aResult.Assign(std::move(name));
#else
aResult.Assign(gAppData->name);
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetID(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().ID;
return NS_OK;
}
aResult.Assign(gAppData->ID);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetVersion(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().version;
return NS_OK;
}
aResult.Assign(gAppData->version);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetPlatformVersion(nsACString& aResult) {
aResult.Assign(gToolkitVersion);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetAppBuildID(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().buildID;
return NS_OK;
}
aResult.Assign(gAppData->buildID);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetPlatformBuildID(nsACString& aResult) {
aResult.Assign(gToolkitBuildID);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetUAName(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().UAName;
return NS_OK;
}
aResult.Assign(gAppData->UAName);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetSourceURL(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().sourceURL;
return NS_OK;
}
aResult.Assign(gAppData->sourceURL);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetUpdateURL(nsACString& aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
aResult = cc->GetAppInfo().updateURL;
return NS_OK;
}
aResult.Assign(gAppData->updateURL);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetLogConsoleErrors(bool* aResult) {
*aResult = gLogConsoleErrors;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::SetLogConsoleErrors(bool aValue) {
gLogConsoleErrors = aValue;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetInSafeMode(bool* aResult) {
*aResult = gSafeMode;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetOS(nsACString& aResult) {
aResult.AssignLiteral(OS_TARGET);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetXPCOMABI(nsACString& aResult) {
#ifdef TARGET_XPCOM_ABI
aResult.AssignLiteral(TARGET_XPCOM_ABI);
return NS_OK;
#else
return NS_ERROR_NOT_AVAILABLE;
#endif
}
NS_IMETHODIMP
nsXULAppInfo::GetWidgetToolkit(nsACString& aResult) {
aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT);
return NS_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(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)
SYNC_ENUMS(SANDBOX_BROKER, RemoteSandboxBroker)
SYNC_ENUMS(FORKSERVER, ForkServer)
// .. and ensure that that is all of them:
static_assert(GeckoProcessType_ForkServer + 1 == GeckoProcessType_End,
"Did not find the final GeckoProcessType");
NS_IMETHODIMP
nsXULAppInfo::GetProcessType(uint32_t* aResult) {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = XRE_GetProcessType();
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetProcessID(uint32_t* aResult) {
#ifdef XP_WIN
*aResult = GetCurrentProcessId();
#else
*aResult = getpid();
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetUniqueProcessID(uint64_t* aResult) {
if (XRE_IsContentProcess()) {
ContentChild* cc = ContentChild::GetSingleton();
*aResult = cc->GetID();
} else {
*aResult = 0;
}
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetRemoteType(nsACString& aRemoteType) {
if (XRE_IsContentProcess()) {
aRemoteType = ContentChild::GetSingleton()->GetRemoteType();
} else {
aRemoteType = NOT_REMOTE_TYPE;
}
return NS_OK;
}
static nsCString gLastAppVersion;
static nsCString gLastAppBuildID;
NS_IMETHODIMP
nsXULAppInfo::GetLastAppVersion(nsACString& aResult) {
if (XRE_IsContentProcess()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!gLastAppVersion.IsVoid() && gLastAppVersion.IsEmpty()) {
NS_WARNING("Attempt to retrieve lastAppVersion before it has been set.");
return NS_ERROR_NOT_AVAILABLE;
}
aResult.Assign(gLastAppVersion);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetLastAppBuildID(nsACString& aResult) {
if (XRE_IsContentProcess()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!gLastAppBuildID.IsVoid() && gLastAppBuildID.IsEmpty()) {
NS_WARNING("Attempt to retrieve lastAppBuildID before it has been set.");
return NS_ERROR_NOT_AVAILABLE;
}
aResult.Assign(gLastAppBuildID);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetFissionAutostart(bool* aResult) {
*aResult = FissionAutostart();
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetFissionExperimentStatus(ExperimentStatus* aResult) {
if (!XRE_IsParentProcess()) {
return NS_ERROR_NOT_AVAILABLE;
}
EnsureFissionAutostartInitialized();
*aResult = gFissionExperimentStatus;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetFissionDecisionStatus(FissionDecisionStatus* aResult) {
if (!XRE_IsParentProcess()) {
return NS_ERROR_NOT_AVAILABLE;
}
EnsureFissionAutostartInitialized();
MOZ_ASSERT(gFissionDecisionStatus != eFissionStatusUnknown);
*aResult = gFissionDecisionStatus;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetFissionDecisionStatusString(nsACString& aResult) {
if (!XRE_IsParentProcess()) {
return NS_ERROR_NOT_AVAILABLE;
}
EnsureFissionAutostartInitialized();
switch (gFissionDecisionStatus) {
case eFissionExperimentControl:
aResult = "experimentControl";
break;
case eFissionExperimentTreatment:
aResult = "experimentTreatment";
break;
case eFissionDisabledByE10sEnv:
aResult = "disabledByE10sEnv";
break;
case eFissionEnabledByEnv:
aResult = "enabledByEnv";
break;
case eFissionDisabledBySafeMode:
aResult = "disabledBySafeMode";
break;
case eFissionEnabledByDefault:
aResult = "enabledByDefault";
break;
case eFissionDisabledByDefault:
aResult = "disabledByDefault";
break;
case eFissionEnabledByUserPref:
aResult = "enabledByUserPref";
break;
case eFissionDisabledByUserPref:
aResult = "disabledByUserPref";
break;
case eFissionDisabledByE10sOther:
aResult = "disabledByE10sOther";
break;
case eFissionEnabledByRollout:
aResult = "enabledByRollout";
break;
default:
MOZ_ASSERT_UNREACHABLE("Unexpected enum value");
}
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetSessionHistoryInParent(bool* aResult) {
*aResult = SessionHistoryInParent();
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetBrowserTabsRemoteAutostart(bool* aResult) {
*aResult = BrowserTabsRemoteAutostart();
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetMaxWebProcessCount(uint32_t* aResult) {
*aResult = mozilla::GetMaxWebProcessCount();
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetAccessibilityEnabled(bool* aResult) {
#ifdef ACCESSIBILITY
*aResult = GetAccService() != nullptr;
#else
*aResult = false;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetAccessibleHandlerUsed(bool* aResult) {
#if defined(ACCESSIBILITY) && defined(XP_WIN)
*aResult = Preferences::GetBool("accessibility.handler.enabled", false) &&
a11y::IsHandlerRegistered();
#else
*aResult = false;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetAccessibilityInstantiator(nsAString& aInstantiator) {
#if defined(ACCESSIBILITY) && defined(XP_WIN)
if (!GetAccService()) {
aInstantiator.Truncate();
return NS_OK;
}
nsAutoString ipClientInfo;
a11y::Compatibility::GetHumanReadableConsumersStr(ipClientInfo);
aInstantiator.Append(ipClientInfo);
aInstantiator.AppendLiteral("|");
nsCOMPtr<nsIFile> oopClientExe;
if (a11y::GetInstantiator(getter_AddRefs(oopClientExe))) {
nsAutoString oopClientInfo;
if (NS_SUCCEEDED(oopClientExe->GetPath(oopClientInfo))) {
aInstantiator.Append(oopClientInfo);
}
}
#else
aInstantiator.Truncate();
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetShouldBlockIncompatJaws(bool* aResult) {
*aResult = false;
#if defined(ACCESSIBILITY) && defined(XP_WIN)
*aResult = mozilla::a11y::Compatibility::IsOldJAWS();
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetIs64Bit(bool* aResult) {
#ifdef HAVE_64BIT_BUILD
*aResult = true;
#else
*aResult = false;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::EnsureContentProcess() {
if (!XRE_IsParentProcess()) return NS_ERROR_NOT_AVAILABLE;
RefPtr<ContentParent> unused =
ContentParent::GetNewOrUsedBrowserProcess(DEFAULT_REMOTE_TYPE);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::InvalidateCachesOnRestart() {
nsCOMPtr<nsIFile> file;
nsresult rv =
NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP, getter_AddRefs(file));
if (NS_FAILED(rv)) return rv;
if (!file) return NS_ERROR_NOT_AVAILABLE;
file->AppendNative(FILE_COMPATIBILITY_INFO);
nsINIParser parser;
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.
return NS_OK;
}
nsAutoCString buf;
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");
return NS_ERROR_NOT_AVAILABLE;
}
static const char kInvalidationHeader[] =
NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
PR_Close(fd);
}
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetReplacedLockTime(PRTime* aReplacedLockTime) {
if (!gProfileLock) return NS_ERROR_NOT_AVAILABLE;
gProfileLock->GetReplacedLockTime(aReplacedLockTime);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetIsReleaseOrBeta(bool* aResult) {
#ifdef RELEASE_OR_BETA
*aResult = true;
#else
*aResult = false;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetIsOfficialBranding(bool* aResult) {
#ifdef MOZ_OFFICIAL_BRANDING
*aResult = true;
#else
*aResult = false;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult) {
aResult.AssignLiteral(MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL));
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetDistributionID(nsACString& aResult) {
aResult.AssignLiteral(MOZ_DISTRIBUTION_ID);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetWindowsDLLBlocklistStatus(bool* aResult) {
#if defined(HAS_DLL_BLOCKLIST)
*aResult = DllBlocklist_CheckStatus();
#else
*aResult = false;
#endif
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetRestartedByOS(bool* aResult) {
*aResult = gRestartedByOS;
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetProcessStartupShortcut(nsAString& aShortcut) {
#if defined(XP_WIN)
if (XRE_IsParentProcess()) {
aShortcut.Assign(gProcessStartupShortcut);
return NS_OK;
}
#endif
return NS_ERROR_NOT_AVAILABLE;
}
#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
// Forward declaration
void SetupLauncherProcessPref();
static Maybe<LauncherRegistryInfo::EnabledState> gLauncherProcessState;
#endif // defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
NS_IMETHODIMP
nsXULAppInfo::GetLauncherProcessState(uint32_t* aResult) {
#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
SetupLauncherProcessPref();
if (!gLauncherProcessState) {
return NS_ERROR_UNEXPECTED;
}
*aResult = static_cast<uint32_t>(gLauncherProcessState.value());
return NS_OK;
#else
return NS_ERROR_NOT_AVAILABLE;
#endif
}
#ifdef XP_WIN
NS_IMETHODIMP
nsXULAppInfo::GetUserCanElevate(bool* aUserCanElevate) {
HANDLE rawToken;
if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken)) {
*aUserCanElevate = false;
return NS_OK;
}
nsAutoHandle token(rawToken);
LauncherResult<TOKEN_ELEVATION_TYPE> elevationType = GetElevationType(token);
if (elevationType.isErr()) {
*aUserCanElevate = false;
return NS_OK;
}
// 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.inspect() == TokenElevationTypeLimited);
return NS_OK;
}
#endif
NS_IMETHODIMP
nsXULAppInfo::GetEnabled(bool* aEnabled) {
*aEnabled = CrashReporter::GetEnabled();
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::SetEnabled(bool aEnabled) {
if (aEnabled) {
if (CrashReporter::GetEnabled()) {
// no point in erroring for double-enabling
return NS_OK;
}
nsCOMPtr<nsIFile> greBinDir;
NS_GetSpecialDirectory(NS_GRE_BIN_DIR, getter_AddRefs(greBinDir));
if (!greBinDir) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIFile> xreBinDirectory = greBinDir;
if (!xreBinDirectory) {
return NS_ERROR_FAILURE;
}
return CrashReporter::SetExceptionHandler(xreBinDirectory, true);
}
if (!CrashReporter::GetEnabled()) {
// no point in erroring for double-disabling
return NS_OK;
}
return CrashReporter::UnsetExceptionHandler();
}
NS_IMETHODIMP
nsXULAppInfo::GetServerURL(nsIURL** aServerURL) {
NS_ENSURE_ARG_POINTER(aServerURL);
if (!CrashReporter::GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
nsAutoCString data;
if (!CrashReporter::GetServerURL(data)) {
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), data);
if (!uri) return NS_ERROR_FAILURE;
nsCOMPtr<nsIURL> url;
url = do_QueryInterface(uri);
NS_ADDREF(*aServerURL = url);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::SetServerURL(nsIURL* aServerURL) {
// Only allow https or http URLs
if (!aServerURL->SchemeIs("http") && !aServerURL->SchemeIs("https")) {
return NS_ERROR_INVALID_ARG;
}
nsAutoCString spec;
nsresult rv = aServerURL->GetSpec(spec);
NS_ENSURE_SUCCESS(rv, rv);
return CrashReporter::SetServerURL(spec);
}
NS_IMETHODIMP
nsXULAppInfo::GetMinidumpPath(nsIFile** aMinidumpPath) {
if (!CrashReporter::GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
nsAutoString path;
if (!CrashReporter::GetMinidumpPath(path)) return NS_ERROR_FAILURE;
nsresult rv = NS_NewLocalFile(path, false, aMinidumpPath);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::SetMinidumpPath(nsIFile* aMinidumpPath) {
nsAutoString path;
nsresult rv = aMinidumpPath->GetPath(path);
NS_ENSURE_SUCCESS(rv, rv);
return CrashReporter::SetMinidumpPath(path);
}
NS_IMETHODIMP
nsXULAppInfo::GetMinidumpForID(const nsAString& aId, nsIFile** aMinidump) {
if (!CrashReporter::GetMinidumpForID(aId, aMinidump)) {
return NS_ERROR_FILE_NOT_FOUND;
}
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::GetExtraFileForID(const nsAString& aId, nsIFile** aExtraFile) {
if (!CrashReporter::GetExtraFileForID(aId, aExtraFile)) {
return NS_ERROR_FILE_NOT_FOUND;
}
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
const nsACString& data) {
CrashReporter::Annotation annotation;
if (!AnnotationFromString(annotation, PromiseFlatCString(key).get())) {
return NS_ERROR_INVALID_ARG;
}
return CrashReporter::AnnotateCrashReport(annotation, data);
}
NS_IMETHODIMP
nsXULAppInfo::RemoveCrashReportAnnotation(const nsACString& key) {
CrashReporter::Annotation annotation;
if (!AnnotationFromString(annotation, PromiseFlatCString(key).get())) {
return NS_ERROR_INVALID_ARG;
}
return CrashReporter::RemoveCrashReportAnnotation(annotation);
}
NS_IMETHODIMP
nsXULAppInfo::IsAnnotationWhitelistedForPing(const nsACString& aValue,
bool* aIsWhitelisted) {
CrashReporter::Annotation annotation;
if (!AnnotationFromString(annotation, PromiseFlatCString(aValue).get())) {
return NS_ERROR_INVALID_ARG;
}
*aIsWhitelisted = CrashReporter::IsAnnotationWhitelistedForPing(annotation);
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data) {
return CrashReporter::AppendAppNotesToCrashReport(data);
}
NS_IMETHODIMP
nsXULAppInfo::RegisterAppMemory(uint64_t pointer, uint64_t len) {
return CrashReporter::RegisterAppMemory((void*)pointer, len);
}
NS_IMETHODIMP
nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo) {
#ifdef XP_WIN
return CrashReporter::WriteMinidumpForException(
static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
NS_IMETHODIMP
nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException) {
#ifdef XP_MACOSX
return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
NS_IMETHODIMP
nsXULAppInfo::GetSubmitReports(bool* aEnabled) {
return CrashReporter::GetSubmitReports(aEnabled);
}
NS_IMETHODIMP
nsXULAppInfo::SetSubmitReports(bool aEnabled) {
return CrashReporter::SetSubmitReports(aEnabled);
}
NS_IMETHODIMP
nsXULAppInfo::UpdateCrashEventsDir() {
CrashReporter::UpdateCrashEventsDir();
return NS_OK;
}
NS_IMETHODIMP
nsXULAppInfo::SaveMemoryReport() {
if (!CrashReporter::GetEnabled()) {
return NS_ERROR_NOT_INITIALIZED;
}
nsCOMPtr<nsIFile> file;
nsresult rv = CrashReporter::GetDefaultMemoryReportFile(getter_AddRefs(file));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
nsString path;
file->GetPath(path);
nsCOMPtr<nsIMemoryInfoDumper> dumper =
do_GetService("@mozilla.org/memory-info-dumper;1");
if (NS_WARN_IF(!dumper)) {
return NS_ERROR_UNEXPECTED;
}
rv = dumper->DumpMemoryReportsToNamedFile(
path, this, file, true /* anonymize */, false /* minimizeMemoryUsage */);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
return NS_OK;
}
// This method is from nsIFInishDumpingCallback.
NS_IMETHODIMP
nsXULAppInfo::Callback(nsISupports* aData) {