Bug 1728653 - Allow a silent start mode r=bytesized,nalexander,application-update-reviewers,mossop

This will allow starting Firefox in the background, and on Windows will allow
closing the last browser window without killing the main process. There is no
plan for actually using this by default in Firefox proper, but it's needed for
some explorations.

There's more to this work that we'll need - this is just the first step. For
instance, we'll need a real way to actually kill firefox on Windows other than
through the task manager (we'll be putting something in the system tray to
allow this.)

The patch wasn't particularly large, so I didn't split out the rename of
MOZ_APP_SILENT_START to MOZ_APP_SILENT_RESTART - let me know if you'd like me
to do that though and I can.

Differential Revision: https://phabricator.services.mozilla.com/D124249
This commit is contained in:
Doug Thayer 2021-09-09 18:09:25 +00:00
Родитель 6e0d14a9c9
Коммит ef2740f793
9 изменённых файлов: 47 добавлений и 27 удалений

Просмотреть файл

@ -341,6 +341,14 @@ int main(int argc, char* argv[], char* envp[]) {
DllBlocklist_Initialize(gBlocklistInitFlags);
#endif
// We will likely only ever support this as a command line argument on Windows
// and OSX, so we're ifdefing here just to not create any expectations.
#if defined(XP_WIN) || defined(XP_MACOSX)
if (argc > 1 && IsArg(argv[1], "silentmode")) {
::putenv(const_cast<char*>("MOZ_APP_SILENT_START=1"));
}
#endif
#if defined(XP_WIN)
// Ideally, we would be able to set our DPI awareness in firefox.exe.manifest

Просмотреть файл

@ -926,13 +926,12 @@ nsDefaultCommandLineHandler.prototype = {
var urilist = [];
if (
AppConstants.platform == "macosx" &&
cmdLine.state == Ci.nsICommandLine.STATE_INITIAL_LAUNCH &&
Services.startup.wasSilentlyRestarted
Services.startup.wasSilentlyStarted
) {
// If we are starting up after a silent restart, don't open a window.
// We also need to make sure that the application doesn't immediately
// exit, so stay in a LastWindowClosingSurvivalArea until a window opens.
// If we are starting up in silent mode, don't open a window. We also need
// to make sure that the application doesn't immediately exit, so stay in
// a LastWindowClosingSurvivalArea until a window opens.
Services.startup.enterLastWindowClosingSurvivalArea();
Services.obs.addObserver(function windowOpenObserver() {
Services.startup.exitLastWindowClosingSurvivalArea();

Просмотреть файл

@ -756,6 +756,7 @@ let JSWINDOWACTORS = {
let startTime = Cu.now();
if (
AppConstants.platform == "macosx" ||
Services.startup.wasSilentlyStarted ||
!Services.prefs.getBoolPref("browser.startup.blankWindow", false)
) {
return;

Просмотреть файл

@ -1666,6 +1666,7 @@ static Result<Ok, PreXULSkeletonUIError> ValidateCmdlineArguments(
static Result<Ok, PreXULSkeletonUIError> ValidateEnvVars() {
if (EnvHasValue("MOZ_SAFE_MODE_RESTART") ||
EnvHasValue("MOZ_APP_SILENT_START") ||
EnvHasValue("MOZ_RESET_PROFILE_RESTART") || EnvHasValue("MOZ_HEADLESS") ||
(EnvHasValue("XRE_PROFILE_PATH") &&
!EnvHasValue("MOZ_SKELETON_UI_RESTARTING"))) {
@ -1861,6 +1862,8 @@ static Result<Ok, PreXULSkeletonUIError> CreateAndStorePreXULSkeletonUIImpl(
static_cast<uint32_t>(PreXULSkeletonUIProgress::Completed));
});
MOZ_TRY(GetSkeletonUILock());
bool explicitProfile = false;
MOZ_TRY(ValidateCmdlineArguments(argc, argv, &explicitProfile));
MOZ_TRY(ValidateEnvVars());
@ -1879,7 +1882,6 @@ static Result<Ok, PreXULSkeletonUIError> CreateAndStorePreXULSkeletonUIImpl(
sAnimatedRects = new Vector<ColorRect>();
MOZ_TRY(LoadGdi32AndUser32Procedures());
MOZ_TRY(GetSkeletonUILock());
if (!explicitProfile) {
MOZ_TRY(CheckForStartWithLastProfile());

Просмотреть файл

@ -161,15 +161,16 @@ nsAppStartup::nsAppStartup()
mInterrupted(false),
mIsSafeModeNecessary(false),
mStartupCrashTrackingEnded(false) {
char* mozAppSilentRestart = PR_GetEnv("MOZ_APP_SILENT_RESTART");
char* mozAppSilentStart = PR_GetEnv("MOZ_APP_SILENT_START");
/* When calling PR_SetEnv() with an empty value the existing variable may
* be unset or set to the empty string depending on the underlying platform
* thus we have to check if the variable is present and not empty. */
mWasSilentlyRestarted =
mozAppSilentRestart && (strcmp(mozAppSilentRestart, "") != 0);
mWasSilentlyStarted =
mozAppSilentStart && (strcmp(mozAppSilentStart, "") != 0);
// Make sure to clear this in case we restart again non-silently.
PR_SetEnv("MOZ_APP_SILENT_RESTART=");
PR_SetEnv("MOZ_APP_SILENT_START=");
}
nsresult nsAppStartup::Init() {
@ -277,6 +278,10 @@ nsAppStartup::Run(void) {
if (!mShuttingDown && mConsiderQuitStopper != 0) {
#ifdef XP_MACOSX
EnterLastWindowClosingSurvivalArea();
#else
if (mWasSilentlyStarted) {
EnterLastWindowClosingSurvivalArea();
}
#endif
mRunning = true;
@ -404,7 +409,7 @@ nsAppStartup::Quit(uint32_t aMode, int aExitCode, bool* aUserAllowedQuit) {
if ((aMode & eSilently) != 0) {
// Mark the next startup as a silent restart.
// See the eSilently definition for details.
PR_SetEnv("MOZ_APP_SILENT_RESTART=1");
PR_SetEnv("MOZ_APP_SILENT_START=1");
}
obsService = mozilla::services::GetObserverService();
@ -414,6 +419,10 @@ nsAppStartup::Quit(uint32_t aMode, int aExitCode, bool* aUserAllowedQuit) {
#ifdef XP_MACOSX
// now even the Mac wants to quit when the last window is closed
ExitLastWindowClosingSurvivalArea();
#else
if (mWasSilentlyStarted) {
ExitLastWindowClosingSurvivalArea();
}
#endif
if (obsService)
obsService->NotifyObservers(nullptr, "quit-application-granted",
@ -585,8 +594,8 @@ nsAppStartup::GetWasRestarted(bool* aResult) {
}
NS_IMETHODIMP
nsAppStartup::GetWasSilentlyRestarted(bool* aResult) {
*aResult = mWasSilentlyRestarted;
nsAppStartup::GetWasSilentlyStarted(bool* aResult) {
*aResult = mWasSilentlyStarted;
return NS_OK;
}

Просмотреть файл

@ -58,7 +58,7 @@ class nsAppStartup final : public nsIAppStartup,
bool mIsSafeModeNecessary; // Whether safe mode is necessary
bool mStartupCrashTrackingEnded; // Whether startup crash tracking has
// already ended
bool mWasSilentlyRestarted; // Was this startup a silent restart?
bool mWasSilentlyStarted; // Was this startup a silent start?
#if defined(XP_WIN)
// Interaction with OS-provided profiling probes

Просмотреть файл

@ -183,9 +183,10 @@ interface nsIAppStartup : nsISupports
/**
* True if this is the startup following a silent restart, i.e. if the
* application was restarted using quit(eSilently*).
* application was restarted using quit(eSilently*), or if the application
* was started with the "silentmode" command line flag.
*/
readonly attribute boolean wasSilentlyRestarted;
readonly attribute boolean wasSilentlyStarted;
/**
* The number of seconds since the OS was last rebooted

Просмотреть файл

@ -294,9 +294,9 @@ static bool sUsingService = false;
// The updater could be run with no callback, but this only happens
// when performing a staged update (see calls to ProcessUpdates), and there
// are already checks for sStagedUpdate when showing UI or elevating.
// b) On macOS, the environment variable MOZ_APP_SILENT_RESTART is set and not
// empty. This is set when Firefox had no windows open for a while and
// restarted to apply updates.
// b) The environment variable MOZ_APP_SILENT_START is set and not empty. This
// is set, for instance, on macOS when Firefox had no windows open for a
// while and restarted to apply updates.
//
// In these cases, the update should be installed silently, so we shouldn't:
// a) show progress UI
@ -2708,11 +2708,11 @@ bool ShouldRunSilently(int argc, NS_tchar** argv) {
}
#endif // MOZ_BACKGROUNDTASKS
#ifdef XP_MACOSX
if (EnvHasValue("MOZ_APP_SILENT_RESTART")) {
#if defined(XP_WIN) || defined(XP_MACOSX)
if (EnvHasValue("MOZ_APP_SILENT_START")) {
return true;
}
#endif // XP_MACOSX
#endif
return false;
}

Просмотреть файл

@ -442,12 +442,12 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
if (restart) {
needElevation = !IsRecursivelyWritable(installDirPath.get());
if (needElevation) {
// Normally we would check this via nsIAppStartup::wasSilentlyRestarted,
// Normally we would check this via nsIAppStartup::wasSilentlyStarted,
// but nsIAppStartup isn't available yet.
char* mozAppSilentRestart = PR_GetEnv("MOZ_APP_SILENT_RESTART");
bool wasSilentlyRestarted =
mozAppSilentRestart && (strcmp(mozAppSilentRestart, "") != 0);
if (wasSilentlyRestarted) {
char* mozAppSilentStart = PR_GetEnv("MOZ_APP_SILENT_START");
bool wasSilentlyStarted =
mozAppSilentStart && (strcmp(mozAppSilentStart, "") != 0);
if (wasSilentlyStarted) {
// Elevation always requires prompting for credentials on macOS. If we
// are trying to restart silently, we must not display UI such as this
// prompt.