Backed out 2 changesets (bug 1827651) as requested by developer CLOSED TREE

Backed out changeset e6a9e84f78d9 (bug 1827651)
Backed out changeset c6020af95de1 (bug 1827651)
This commit is contained in:
Norisz Fay 2024-08-29 22:57:27 +03:00
Родитель 9e27b342a4
Коммит 1dc5980f77
20 изменённых файлов: 255 добавлений и 517 удалений

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

@ -11,14 +11,3 @@ endif
endif
include $(topsrcdir)/config/rules.mk
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
XPCSHELLTESTDIR = $(topobjdir)/_tests/xpcshell/toolkit/mozapps/update/tests/data/
libs::
$(NSINSTALL) -D $(DIST)/bin/callback_app.app
rsync -a -C $(srcdir)/macbuild/Contents $(DIST)/bin/callback_app.app
$(NSINSTALL) -D $(DIST)/bin/callback_app.app/Contents/MacOS
$(NSINSTALL) $(XPCSHELLTESTDIR)/TestAUSHelper $(DIST)/bin/callback_app.app/Contents/MacOS
cp -R $(DIST)/bin/callback_app.app $(XPCSHELLTESTDIR)
endif

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

@ -81,37 +81,6 @@ static bool CheckMsg(const NS_tchar* path, const char* expected) {
return isMatch;
}
static bool BuildLogFilePath(NS_tchar* aLogFilePath, size_t aBufferSize,
NS_tchar** aArgv) {
#ifdef XP_MACOSX
// Our tests on macOS require absolute paths to log files, as relative paths
// will be interpreted as relative to the root of the file system, i.e. '/',
// which is a read-only location where our tests can't write to.
//
// This finds the absolute path to `callback_app.app`, which will usually be:
// <abs-path>/dir.app/Contents/MacOS/
//
NS_tchar* callbackAppBundle = NS_tstrstr(aArgv[0], "callback_app.app");
if (!callbackAppBundle) {
return false;
}
// This appends the log file name to the same absolute path as
// `callback_app.app`, which is what our tests expect.
if (!NS_tvsnprintf(aLogFilePath, aBufferSize / sizeof(aLogFilePath[0]),
NS_T("%.*s%s"), callbackAppBundle - aArgv[0], aArgv[0],
aArgv[2])) {
return false;
}
#else
if (!NS_tvsnprintf(aLogFilePath, aBufferSize / sizeof(aLogFilePath[0]),
NS_T("%s"), aArgv[2])) {
return false;
}
#endif
return true;
}
int NS_main(int argc, NS_tchar** argv) {
if (argc == 2) {
if (!NS_tstrcmp(argv[1], NS_T("post-update-async")) ||
@ -360,7 +329,9 @@ int NS_main(int argc, NS_tchar** argv) {
::umask(umask);
NS_tchar logFilePath[MAXPATHLEN];
if (!BuildLogFilePath(logFilePath, sizeof(logFilePath), argv)) {
if (!NS_tvsnprintf(logFilePath,
sizeof(logFilePath) / sizeof(logFilePath[0]), NS_T("%s"),
argv[2])) {
return 1;
}
@ -503,7 +474,9 @@ int NS_main(int argc, NS_tchar** argv) {
{
// Command line argument test helper section
NS_tchar logFilePath[MAXPATHLEN];
if (!BuildLogFilePath(logFilePath, sizeof(logFilePath), argv)) {
if (!NS_tvsnprintf(logFilePath,
sizeof(logFilePath) / sizeof(logFilePath[0]), NS_T("%s"),
argv[2])) {
return 1;
}

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

@ -315,13 +315,10 @@ function moveRealUpdater() {
return (async function () {
try {
// Move away the real updater
let updaterBackup = getGREBinDir();
let updater = getGREBinDir();
let greBinDir = getGREBinDir();
let updater = greBinDir.clone();
updater.append(FILE_UPDATER_BIN);
if (AppConstants.platform == "macosx") {
updaterBackup = updaterBackup.parent.parent.parent;
}
updater.moveTo(updaterBackup, FILE_UPDATER_BIN_BAK);
updater.moveTo(greBinDir, FILE_UPDATER_BIN_BAK);
let greDir = getGREDir();
let updateSettingsIni = greDir.clone();
@ -409,9 +406,6 @@ function restoreUpdaterBackup() {
let greBinDir = getGREBinDir();
let updater = greBinDir.clone();
let updaterBackup = greBinDir.clone();
if (AppConstants.platform == "macosx") {
updaterBackup = updaterBackup.parent.parent.parent;
}
updater.append(FILE_UPDATER_BIN);
updaterBackup.append(FILE_UPDATER_BIN_BAK);
if (updaterBackup.exists()) {

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

@ -77,7 +77,6 @@ const FILE_BACKUP_UPDATE_ELEVATED_LOG = "backup-update-elevated.log";
const FILE_BACKUP_UPDATE_LOG = "backup-update.log";
const FILE_CHANNEL_PREFS =
AppConstants.platform == "macosx" ? "ChannelPrefs" : "channel-prefs.js";
const FILE_INFO_PLIST = "Info.plist";
const FILE_LAST_UPDATE_ELEVATED_LOG = "last-update-elevated.log";
const FILE_LAST_UPDATE_LOG = "last-update.log";
const FILE_PRECOMPLETE = "precomplete";
@ -100,9 +99,6 @@ const UPDATE_SETTINGS_CONTENTS =
"[Settings]\nACCEPTED_MAR_CHANNEL_IDS=xpcshell-test\n";
const PRECOMPLETE_CONTENTS = 'rmdir "nonexistent_dir/"\n';
const DIR_APP_INFO_PLIST_FILE_CONTENTS =
'<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundleDevelopmentRegion</key><string>English</string><key>CFBundleDisplayName</key><string>dir</string><key>CFBundleExecutable</key><string>firefox</string><key>CFBundleIdentifier</key><string>org.mozilla.firefox</string><key>CFBundleInfoDictionaryVersion</key><string>6.0</string><key>CFBundleName</key><string>dir</string><key>CFBundlePackageType</key><string>APPL</string><key>CFBundleSignature</key><string>????</string><key>CFBundleVersion</key><string>1.0</string></dict></plist>';
const PR_RDWR = 0x04;
const PR_CREATE_FILE = 0x08;
const PR_TRUNCATE = 0x20;

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

@ -45,13 +45,9 @@ const Cm = Components.manager;
/* global MOZ_VERIFY_MAR_SIGNATURE, IS_AUTHENTICODE_CHECK_ENABLED */
load("../data/xpcshellConstantsPP.js");
// Note: DIR_CONTENTS, DIR_MACOS and DIR_RESOURCES only differ on macOS. They
// default to "" on all other platforms.
const DIR_CONTENTS = AppConstants.platform == "macosx" ? "Contents/" : "";
const DIR_MACOS =
AppConstants.platform == "macosx" ? DIR_CONTENTS + "MacOS/" : "";
const DIR_MACOS = AppConstants.platform == "macosx" ? "Contents/MacOS/" : "";
const DIR_RESOURCES =
AppConstants.platform == "macosx" ? DIR_CONTENTS + "Resources/" : "";
AppConstants.platform == "macosx" ? "Contents/Resources/" : "";
const TEST_FILE_SUFFIX = AppConstants.platform == "macosx" ? "_mac" : "";
const FILE_COMPLETE_MAR = "complete" + TEST_FILE_SUFFIX + ".mar";
const FILE_PARTIAL_MAR = "partial" + TEST_FILE_SUFFIX + ".mar";
@ -79,19 +75,13 @@ const APP_BIN_SUFFIX =
AppConstants.platform == "linux" ? "-bin" : mozinfo.bin_suffix;
const FILE_APP_BIN = AppConstants.MOZ_APP_NAME + APP_BIN_SUFFIX;
const FILE_COMPLETE_EXE = "complete.exe";
const FILE_HELPER_BIN =
AppConstants.platform == "macosx"
? "callback_app.app/Contents/MacOS/TestAUSHelper"
: "TestAUSHelper" + mozinfo.bin_suffix;
const FILE_HELPER_APP =
AppConstants.platform == "macosx" ? "callback_app.app" : FILE_HELPER_BIN;
const FILE_HELPER_BIN = "TestAUSHelper" + mozinfo.bin_suffix;
const FILE_MAINTENANCE_SERVICE_BIN = "maintenanceservice.exe";
const FILE_MAINTENANCE_SERVICE_INSTALLER_BIN =
"maintenanceservice_installer.exe";
const FILE_OLD_VERSION_MAR = "old_version.mar";
const FILE_PARTIAL_EXE = "partial.exe";
const FILE_UPDATER_BIN =
"updater" + (AppConstants.platform == "macosx" ? ".app" : mozinfo.bin_suffix);
const FILE_UPDATER_BIN = "updater" + mozinfo.bin_suffix;
const PERFORMING_STAGED_UPDATE = "Performing a staged update";
const CALL_QUIT = "calling QuitProgressUI";
@ -155,21 +145,8 @@ var gPIDPersistProcess;
// Variables are used instead of contants so tests can override these values if
// necessary.
var gCallbackBinFile = "callback_app" + mozinfo.bin_suffix;
var gCallbackArgs = ["./", "callback.log", "Test Arg 2", "Test Arg 3"];
var gCallbackApp = (() => {
if (AppConstants.platform == "macosx") {
return "callback_app.app";
}
return "callback_app" + mozinfo.bin_suffix;
})();
var gCallbackBinFile = (() => {
if (AppConstants.platform == "macosx") {
return FILE_HELPER_BIN;
}
return "callback_app" + mozinfo.bin_suffix;
})();
var gPostUpdateBinFile = "postup_app" + mozinfo.bin_suffix;
var gTimeoutRuns = 0;
@ -250,43 +227,7 @@ var gTestFilesCommonMac = [
description: "Should never change",
fileName: FILE_UPDATE_SETTINGS_FRAMEWORK,
relPathDir:
DIR_MACOS + "updater.app/Contents/Frameworks/UpdateSettings.framework/",
originalContents: null,
compareContents: null,
originalFile: null,
compareFile: null,
originalPerms: null,
comparePerms: null,
existingFile: true,
},
{
description: "Should never change",
fileName: FILE_INFO_PLIST,
relPathDir: DIR_CONTENTS,
originalContents: DIR_APP_INFO_PLIST_FILE_CONTENTS,
compareContents: DIR_APP_INFO_PLIST_FILE_CONTENTS,
originalFile: null,
compareFile: null,
originalPerms: null,
comparePerms: null,
existingFile: true,
},
{
description: "Should never change",
fileName: FILE_INFO_PLIST,
relPathDir: DIR_MACOS + "updater.app/Contents/",
originalContents: null,
compareContents: null,
originalFile: null,
compareFile: null,
originalPerms: null,
comparePerms: null,
existingFile: true,
},
{
description: "Should never change",
fileName: FILE_INFO_PLIST,
relPathDir: DIR_MACOS + "callback_app.app/Contents/",
"Contents/MacOS/updater.app/Contents/Frameworks/UpdateSettings.framework/",
originalContents: null,
compareContents: null,
originalFile: null,
@ -1058,10 +999,10 @@ function setupTestCommon(aAppUpdateAutoEnabled = false, aAllowBits = false) {
);
syncManager.resetLock();
// Remove the updates directory on Windows and macOS which is located
// Remove the updates directory on Windows and Mac OS X which is located
// outside of the application directory after the call to adjustGeneralPaths
// has set it up. Since the test hasn't run yet, the directory shouldn't
// exist and failure to remove the directory should be non-fatal for the test.
// has set it up. Since the test hasn't ran yet and the directory shouldn't
// exist this is non-fatal for the test.
if (AppConstants.platform == "win" || AppConstants.platform == "macosx") {
let updatesDir = getMockUpdRootD();
if (updatesDir.exists()) {
@ -1560,7 +1501,7 @@ function getApplyDirPath() {
* update will be applied.
*
* The files for the update are located two directories below the apply to
* directory since macOS sets the last modified time for the root directory
* directory since Mac OS X sets the last modified time for the root directory
* to the current time and if the update changes any files in the root directory
* then it wouldn't be possible to test (bug 600098).
*
@ -1968,21 +1909,6 @@ function removeUpdateInProgressLockFile(aDir) {
Assert.ok(!file.exists(), MSG_SHOULD_NOT_EXIST + getMsgPath(file.path));
}
function stripQuarantineBitFromPath(aPath) {
if (AppConstants.platform != "macosx") {
do_throw("macOS-only function called by a different platform!");
}
let args = ["-dr", "com.apple.quarantine", aPath];
let stripQuarantineBitProcess = Cc[
"@mozilla.org/process/util;1"
].createInstance(Ci.nsIProcess);
let xattrBin = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
xattrBin.initWithPath("/usr/bin/xattr");
stripQuarantineBitProcess.init(xattrBin);
stripQuarantineBitProcess.run(true, args, args.length);
}
/**
* Copies the test updater to the GRE binary directory and returns the nsIFile
* for the copied test updater.
@ -1990,15 +1916,15 @@ function stripQuarantineBitFromPath(aPath) {
* @return nsIFIle for the copied test updater.
*/
function copyTestUpdaterToBinDir() {
let testUpdater = getTestDirFile(FILE_UPDATER_BIN);
let updaterLeafName =
AppConstants.platform == "macosx" ? "updater.app" : FILE_UPDATER_BIN;
let testUpdater = getTestDirFile(updaterLeafName);
let updater = getGREBinDir();
updater.append(FILE_UPDATER_BIN);
updater.append(updaterLeafName);
if (!updater.exists()) {
testUpdater.copyToFollowingLinks(updater.parent, FILE_UPDATER_BIN);
testUpdater.copyToFollowingLinks(updater.parent, updaterLeafName);
}
if (AppConstants.platform == "macosx") {
stripQuarantineBitFromPath(updater.path);
updater.append("Contents");
updater.append("MacOS");
updater.append("org.mozilla.updater");
@ -2125,8 +2051,8 @@ function runUpdate(
let svcOriginalLog;
if (gIsServiceTest) {
copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_BIN, DIR_MACOS);
copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_INSTALLER_BIN, DIR_MACOS);
copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_BIN, false);
copyFileToTestAppDir(FILE_MAINTENANCE_SERVICE_INSTALLER_BIN, false);
if (aCheckSvcLog) {
svcOriginalLog = readServiceLogFile();
}
@ -2141,7 +2067,6 @@ function runUpdate(
if (!gUpdateBin) {
gUpdateBin = copyTestUpdaterToBinDir();
}
Assert.ok(
gUpdateBin.exists(),
MSG_SHOULD_EXIST + getMsgPath(gUpdateBin.path)
@ -2152,7 +2077,7 @@ function runUpdate(
let applyToDirPath = aApplyToDirPath || getApplyDirFile().path;
let stageDirPath = aApplyToDirPath || getStageDirFile().path;
let callbackApp = getApplyDirFile(DIR_MACOS + gCallbackApp);
let callbackApp = getApplyDirFile(DIR_RESOURCES + gCallbackBinFile);
Assert.ok(
callbackApp.exists(),
MSG_SHOULD_EXIST + ", path: " + callbackApp.path
@ -2623,19 +2548,19 @@ function setupAppFiles({ requiresOmnijar = false } = {}) {
// Required files for the application or the test that aren't listed in the
// dependentlibs.list file.
let appFiles = [
{ relPath: FILE_APP_BIN, inDir: DIR_MACOS },
{ relPath: FILE_APPLICATION_INI, inDir: DIR_RESOURCES },
{ relPath: "dependentlibs.list", inDir: DIR_RESOURCES },
{ relPath: FILE_APP_BIN, inGreDir: false },
{ relPath: FILE_APPLICATION_INI, inGreDir: true },
{ relPath: "dependentlibs.list", inGreDir: true },
];
if (requiresOmnijar) {
appFiles.push({ relPath: AppConstants.OMNIJAR_NAME, inDir: DIR_RESOURCES });
appFiles.push({ relPath: AppConstants.OMNIJAR_NAME, inGreDir: true });
if (AppConstants.MOZ_BUILD_APP == "browser") {
// Only Firefox uses an app-specific omnijar.
appFiles.push({
relPath: "browser/" + AppConstants.OMNIJAR_NAME,
inDir: DIR_RESOURCES,
inGreDir: true,
});
}
}
@ -2644,8 +2569,8 @@ function setupAppFiles({ requiresOmnijar = false } = {}) {
// symlinked or copied.
if (AppConstants.platform == "linux") {
appFiles.push(
{ relPath: "icons/updater.png", inDir: DIR_RESOURCES },
{ relPath: "libsoftokn3.so", inDir: DIR_RESOURCES }
{ relPath: "icons/updater.png", inGreDir: true },
{ relPath: "libsoftokn3.so", inGreDir: true }
);
}
@ -2663,13 +2588,13 @@ function setupAppFiles({ requiresOmnijar = false } = {}) {
let line = {};
do {
hasMore = fis.readLine(line);
appFiles.push({ relPath: line.value, inDir: DIR_MACOS });
appFiles.push({ relPath: line.value, inGreDir: false });
} while (hasMore);
fis.close();
appFiles.forEach(function CMAF_FLN_FE(aAppFile) {
copyFileToTestAppDir(aAppFile.relPath, aAppFile.inDir);
copyFileToTestAppDir(aAppFile.relPath, aAppFile.inGreDir);
});
copyTestUpdaterToBinDir();
@ -2687,39 +2612,18 @@ function setupAppFiles({ requiresOmnijar = false } = {}) {
* @param aFileRelPath
* The relative path to the source and the destination of the file to
* copy.
* @param aDir
* The relative subdirectory within the .app bundle on macOS. This is
* ignored on all other platforms.
* @param aInGreDir
* Whether the file is located in the GRE directory which is
* <bundle>/Contents/Resources on Mac OS X and is the installation
* directory on all other platforms. If false the file must be in the
* GRE Binary directory which is <bundle>/Contents/MacOS on Mac OS X
* and is the installation directory on on all other platforms.
*/
function copyFileToTestAppDir(aFileRelPath, aDir) {
let srcFile;
let destFile;
function copyFileToTestAppDir(aFileRelPath, aInGreDir) {
// gGREDirOrig and gGREBinDirOrig must always be cloned when changing its
// properties
if (AppConstants.platform == "macosx") {
switch (aDir) {
case DIR_RESOURCES:
srcFile = gGREDirOrig.clone();
destFile = getGREDir();
break;
case DIR_MACOS:
srcFile = gGREBinDirOrig.clone();
destFile = getGREBinDir();
break;
case DIR_CONTENTS:
srcFile = gGREBinDirOrig.parent.clone();
destFile = getGREBinDir().parent;
break;
default:
debugDump("invalid path given. Path: " + aDir);
break;
}
} else {
srcFile = gGREDirOrig.clone();
destFile = getGREDir();
}
let srcFile = aInGreDir ? gGREDirOrig.clone() : gGREBinDirOrig.clone();
let destFile = aInGreDir ? getGREDir() : getGREBinDir();
let fileRelPath = aFileRelPath;
let pathParts = fileRelPath.split("/");
for (let i = 0; i < pathParts.length; i++) {
@ -2736,6 +2640,10 @@ function copyFileToTestAppDir(aFileRelPath, aDir) {
".app exists. Path: " +
srcFile.path
);
// gGREDirOrig and gGREBinDirOrig must always be cloned when changing its
// properties
srcFile = aInGreDir ? gGREDirOrig.clone() : gGREBinDirOrig.clone();
destFile = aInGreDir ? getGREDir() : getGREBinDir();
for (let i = 0; i < pathParts.length; i++) {
if (pathParts[i]) {
srcFile.append(
@ -3272,14 +3180,11 @@ async function setupUpdaterTest(
let mar = getTestDirFile(aMarFile);
mar.copyToFollowingLinks(updatesPatchDir, FILE_UPDATE_MAR);
let helperApp = getTestDirFile(FILE_HELPER_APP);
let helperBin = getTestDirFile(FILE_HELPER_BIN);
helperApp.permissions = PERMS_DIRECTORY;
helperBin.permissions = PERMS_DIRECTORY;
let afterApplyBinDir = getApplyDirFile(DIR_MACOS);
let afterApplyBinDir = getApplyDirFile(DIR_RESOURCES);
helperBin.copyToFollowingLinks(afterApplyBinDir, gCallbackBinFile);
helperBin.copyToFollowingLinks(afterApplyBinDir, gPostUpdateBinFile);
helperApp.copyToFollowingLinks(afterApplyBinDir, gCallbackApp);
// On macOS, some test files (like the Update Settings file) may be within the
// updater app bundle, so make sure it is in place now in case we want to
@ -3288,10 +3193,6 @@ async function setupUpdaterTest(
gUpdateBin = copyTestUpdaterToBinDir();
}
if (AppConstants.platform == "macosx") {
stripQuarantineBitFromPath(afterApplyBinDir.parent.parent.path);
}
gTestFiles.forEach(function SUT_TF_FE(aTestFile) {
debugDump("start - setup test file: " + aTestFile.fileName);
if (aTestFile.originalFile || aTestFile.originalContents) {
@ -3465,7 +3366,11 @@ function createUpdaterINI(
}
let exeRelPathMac =
"ExeRelPath=" + aExeRelPathPrefix + DIR_MACOS + gPostUpdateBinFile + "\n";
"ExeRelPath=" +
aExeRelPathPrefix +
DIR_RESOURCES +
gPostUpdateBinFile +
"\n";
let exeRelPathWin =
"ExeRelPath=" + aExeRelPathPrefix + gPostUpdateBinFile + "\n";
let updaterIniContents =
@ -4139,10 +4044,9 @@ function checkFilesAfterUpdateCommon(aStageDirExists, aToBeDeletedDirExists) {
* parameter passed to the callback executable (in the apply directory).
*/
function checkCallbackLog(
appLaunchLog = getApplyDirFile(DIR_MACOS + gCallbackArgs[1])
appLaunchLog = getApplyDirFile(DIR_RESOURCES + gCallbackArgs[1])
) {
if (!appLaunchLog.exists()) {
debugDump("Callback log does not exist yet. Path: " + appLaunchLog.path);
// Uses do_timeout instead of do_execute_soon to lessen log spew.
do_timeout(FILE_IN_USE_TIMEOUT_MS, checkCallbackLog);
return;
@ -4203,7 +4107,7 @@ function checkCallbackLog(
* The string to append to the post update test helper binary path.
*/
function getPostUpdateFile(aSuffix) {
return getApplyDirFile(DIR_MACOS + gPostUpdateBinFile + aSuffix);
return getApplyDirFile(DIR_RESOURCES + gPostUpdateBinFile + aSuffix);
}
/**

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

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleDisplayName</key>
<string>callback_app</string>
<key>CFBundleExecutable</key>
<string>TestAUSHelper</string>
<key>CFBundleIdentifier</key>
<string>org.mozilla.TestAUSHelper</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>callback_app</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
</dict>
</plist>

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

@ -11,7 +11,7 @@ async function run_test() {
gTestFiles = gTestFilesCompleteSuccess;
gTestDirs = gTestDirsCompleteSuccess;
await setupUpdaterTest(FILE_COMPLETE_MAR, false);
await runHelperFileInUse(DIR_MACOS + gCallbackBinFile, false);
await runHelperFileInUse(DIR_RESOURCES + gCallbackBinFile, false);
runUpdate(STATE_SUCCEEDED, false, 0, true);
await waitForHelperExit();
await checkPostUpdateAppLog();

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

@ -16,9 +16,9 @@ async function run_test() {
// Our callback is `TestAUSHelper check-umask <umask from before updating>`.
// Including the umask from before updating as an argument allows to re-use
// the callback log checking code below. The argument is also used as the log
// the callback log checking code below. The argument is also used as the log
// file name, so we prefix it with "umask" so that it doesn't clash with
// numericfile and directory names in the update data. In particular, "2"
// numericfile and directory names in the update data. In particular, "2"
// clashes with an existing directory name in the update data, leading to
// failing tests.
let umask = Services.sysinfo.getProperty("umask");
@ -36,7 +36,7 @@ async function run_test() {
await checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
// This compares the callback arguments given, including the umask before
// updating, to the umask set when the app callback is launched. They should
// updating, to the umask set when the app callback is launched. They should
// be the same.
checkCallbackLog();
checkCallbackLog(getApplyDirFile(DIR_RESOURCES + "callback_app.log"));
}

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

@ -30,89 +30,128 @@ class MacAutoreleasePool {
NSAutoreleasePool* mPool;
};
/**
* Helper to launch macOS tasks via NSTask and wait for the launched task to
* terminate.
#if defined(__x86_64__)
/*
* Returns true if the process is running under Rosetta translation. Returns
* false if running natively or if an error was encountered. We use the
* `sysctl.proc_translated` sysctl which is documented by Apple to be used
* for this purpose.
*/
static void LaunchTask(NSString* aPath, NSArray* aArguments) {
MacAutoreleasePool pool;
NSTask* task = [[NSTask alloc] init];
[task setExecutableURL:[NSURL fileURLWithPath:aPath]];
if (aArguments) {
[task setArguments:aArguments];
}
[task launchAndReturnError:nil];
[task waitUntilExit];
[task release];
}
static void RegisterAppWithLaunchServices(NSString* aBundlePath) {
MacAutoreleasePool pool;
@try {
OSStatus status =
LSRegisterURL((CFURLRef)[NSURL fileURLWithPath:aBundlePath], YES);
if (status != noErr) {
NSLog(@"We failed to register the app in the Launch Services database, "
@"which may lead to a failure to launch the app. Launch path: %@",
aBundlePath);
bool IsProcessRosettaTranslated() {
int ret = 0;
size_t size = sizeof(ret);
if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) {
if (errno != ENOENT) {
fprintf(stderr, "Failed to check for translation environment\n");
}
} @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason);
return false;
}
return (ret == 1);
}
static void StripQuarantineBit(NSString* aBundlePath) {
MacAutoreleasePool pool;
// Returns true if the binary at |executablePath| can be executed natively
// on an arm64 Mac. Returns false otherwise or if an error occurred.
bool IsBinaryArmExecutable(const char* executablePath) {
bool isArmExecutable = false;
NSArray* arguments = @[ @"-dr", @"com.apple.quarantine", aBundlePath ];
LaunchTask(@"/usr/bin/xattr", arguments);
CFURLRef url = ::CFURLCreateFromFileSystemRepresentation(
kCFAllocatorDefault, (const UInt8*)executablePath, strlen(executablePath),
false);
if (!url) {
return false;
}
CFArrayRef archs = ::CFBundleCopyExecutableArchitecturesForURL(url);
if (!archs) {
CFRelease(url);
return false;
}
CFIndex archCount = ::CFArrayGetCount(archs);
for (CFIndex i = 0; i < archCount; i++) {
CFNumberRef currentArch =
static_cast<CFNumberRef>(::CFArrayGetValueAtIndex(archs, i));
int currentArchInt = 0;
if (!::CFNumberGetValue(currentArch, kCFNumberIntType, &currentArchInt)) {
continue;
}
if (currentArchInt == kCFBundleExecutableArchitectureARM64) {
isArmExecutable = true;
break;
}
}
CFRelease(url);
CFRelease(archs);
return isArmExecutable;
}
void LaunchMacApp(int argc, const char** argv) {
// Returns true if the executable provided in |executablePath| should be
// launched with a preference for arm64. After updating from an x64 version
// running under Rosetta, if the update is to a universal binary with arm64
// support we want to switch to arm64 execution mode. Returns true if those
// conditions are met and the arch(1) utility at |archPath| is executable.
// It should be safe to always launch with arch and fallback to x64, but we
// limit its use to the only scenario it is necessary to minimize risk.
bool ShouldPreferArmLaunch(const char* archPath, const char* executablePath) {
// If not running under Rosetta, we are not on arm64 hardware.
if (!IsProcessRosettaTranslated()) {
return false;
}
// Ensure the arch(1) utility is present and executable.
NSFileManager* fileMgr = [NSFileManager defaultManager];
NSString* archPathString = [NSString stringWithUTF8String:archPath];
if (![fileMgr isExecutableFileAtPath:archPathString]) {
return false;
}
// Ensure the binary can be run natively on arm64.
return IsBinaryArmExecutable(executablePath);
}
#endif // __x86_64__
void LaunchChild(int argc, const char** argv) {
MacAutoreleasePool pool;
@try {
NSString* launchPath = [NSString stringWithUTF8String:argv[0]];
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:argc - 1];
bool preferArmLaunch = false;
#if defined(__x86_64__)
// When running under Rosetta, child processes inherit the architecture
// preference of their parent and therefore universal binaries launched
// by an emulated x64 process will launch in x64 mode. If we are running
// under Rosetta, launch the child process with a preference for arm64 so
// that we will switch to arm64 execution if we have just updated from
// x64 to a universal build. This includes if we were already a universal
// build and the user is intentionally running under Rosetta.
preferArmLaunch = ShouldPreferArmLaunch(ARCH_PATH, argv[0]);
#endif // __x86_64__
NSString* launchPath;
NSMutableArray* arguments;
if (preferArmLaunch) {
launchPath = [NSString stringWithUTF8String:ARCH_PATH];
// Size the arguments array to include all the arguments
// in |argv| plus two arguments to pass to the arch(1) utility.
arguments = [NSMutableArray arrayWithCapacity:argc + 2];
[arguments addObject:[NSString stringWithUTF8String:"-arm64"]];
[arguments addObject:[NSString stringWithUTF8String:"-x86_64"]];
// Add the first argument from |argv|. The rest are added below.
[arguments addObject:[NSString stringWithUTF8String:argv[0]]];
} else {
launchPath = [NSString stringWithUTF8String:argv[0]];
arguments = [NSMutableArray arrayWithCapacity:argc - 1];
}
for (int i = 1; i < argc; i++) {
[arguments addObject:[NSString stringWithUTF8String:argv[i]]];
}
if (![launchPath hasSuffix:@".app"]) {
// We only support launching applications inside .app bundles.
NSLog(@"The updater attempted to launch an app that was not a .app "
@"bundle. Please verify launch path: %@",
launchPath);
return;
}
StripQuarantineBit(launchPath);
RegisterAppWithLaunchServices(launchPath);
// We use NSWorkspace to register the application into the
// `TALAppsToRelaunchAtLogin` list and allow for macOS session resume.
// This API only works with `.app`s.
__block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSWorkspaceOpenConfiguration* config =
[NSWorkspaceOpenConfiguration configuration];
[config setArguments:arguments];
[config setCreatesNewApplicationInstance:YES];
[config setEnvironment:[[NSProcessInfo processInfo] environment]];
[[NSWorkspace sharedWorkspace]
openApplicationAtURL:[NSURL fileURLWithPath:launchPath]
configuration:config
completionHandler:^(NSRunningApplication* aChild, NSError* aError) {
if (aError) {
NSLog(@"launchchild_osx: Failed to run application. Error: %@",
aError);
}
dispatch_semaphore_signal(semaphore);
}];
// We use a semaphore to wait for the application to launch.
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
[NSTask launchedTaskWithLaunchPath:launchPath arguments:arguments];
} @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason);
}
@ -241,10 +280,11 @@ void CleanupElevatedMacUpdate(bool aFailureOccurred) {
error:nil];
[manager removeItemAtPath:@"/Library/LaunchDaemons/org.mozilla.updater.plist"
error:nil];
const char* launchctlArgs[] = {"/bin/launchctl", "remove",
"org.mozilla.updater"};
// The following call will terminate the current process due to the "remove"
// argument.
LaunchTask(@"/bin/launchctl", @[ @"remove", @"org.mozilla.updater" ]);
// argument in launchctlArgs.
LaunchChild(3, launchctlArgs);
}
// Note: Caller is responsible for freeing aArgv.
@ -470,6 +510,31 @@ void SetGroupOwnershipAndPermissions(const char* aAppBundle) {
}
}
/**
* Helper to launch macOS tasks via NSTask.
*/
static void LaunchTask(NSString* aPath, NSArray* aArguments) {
NSTask* task = [[NSTask alloc] init];
[task setExecutableURL:[NSURL fileURLWithPath:aPath]];
if (aArguments) {
[task setArguments:aArguments];
}
[task launchAndReturnError:nil];
[task release];
}
static void RegisterAppWithLaunchServices(NSString* aBundlePath) {
NSArray* arguments = @[ @"-f", aBundlePath ];
LaunchTask(@"/System/Library/Frameworks/CoreServices.framework/Frameworks/"
@"LaunchServices.framework/Support/lsregister",
arguments);
}
static void StripQuarantineBit(NSString* aBundlePath) {
NSArray* arguments = @[ @"-d", @"com.apple.quarantine", aBundlePath ];
LaunchTask(@"/usr/bin/xattr", arguments);
}
bool PerformInstallationFromDMG(int argc, char** argv) {
MacAutoreleasePool pool;
if (argc < 4) {
@ -480,8 +545,8 @@ bool PerformInstallationFromDMG(int argc, char** argv) {
if ([[NSFileManager defaultManager] copyItemAtPath:bundlePath
toPath:destPath
error:nil]) {
StripQuarantineBit(destPath);
RegisterAppWithLaunchServices(destPath);
StripQuarantineBit(destPath);
return true;
}
return false;

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

@ -27,7 +27,6 @@ ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
# Copy for xpcshell tests
$(NSINSTALL) -D $(XPCSHELLTESTDIR)/data/updater-xpcshell.app
rsync -a -C --exclude '*.in' $(srcdir)/../macbuild/Contents $(XPCSHELLTESTDIR)/data/updater-xpcshell.app
$(NSINSTALL) $(DIST)/bin/Info.plist $(XPCSHELLTESTDIR)/data/updater-xpcshell.app/Contents
$(call py_action,preprocessor updater-xpcshell.app/Contents/Resources/English.lproj/InfoPlist.strings,-Fsubstitution --output-encoding utf-16 -DAPP_NAME='$(MOZ_APP_DISPLAYNAME)' $(srcdir)/../macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in -o $(XPCSHELLTESTDIR)/data/updater-xpcshell.app/Contents/Resources/English.lproj/InfoPlist.strings)
$(NSINSTALL) -D $(XPCSHELLTESTDIR)/data/updater-xpcshell.app/Contents/MacOS
$(NSINSTALL) $(FINAL_TARGET)/updater-xpcshell $(XPCSHELLTESTDIR)/data/updater-xpcshell.app/Contents/MacOS

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

@ -74,7 +74,7 @@
void CleanupElevatedMacUpdate(bool aFailureOccurred);
bool IsOwnedByGroupAdmin(const char* aAppBundle);
bool IsRecursivelyWritable(const char* aPath);
void LaunchMacApp(int argc, const char** argv);
void LaunchChild(int argc, const char** argv);
void LaunchMacPostProcess(const char* aAppBundle);
bool ObtainUpdaterArguments(int* aArgc, char*** aArgv,
MARChannelStringTable* aMARStrings);
@ -2160,7 +2160,7 @@ static void LaunchCallbackApp(const NS_tchar* workingDir, int argc,
#if defined(USE_EXECV)
execv(argv[0], argv);
#elif defined(XP_MACOSX)
LaunchMacApp(argc, (const char**)argv);
LaunchChild(argc, (const char**)argv);
#elif defined(XP_WIN)
// Do not allow the callback to run when running an update through the
// service as session 0. The unelevated updater.exe will do the launching.

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

@ -7,19 +7,9 @@
#define MacLaunchHelper_h_
#include <stdint.h>
#include <unistd.h>
#ifdef __OBJC__
# include <Foundation/Foundation.h>
namespace mozilla::MacLaunchHelper {
void LaunchMacAppWithBundle(NSString* aBundlePath,
NSArray* aArguments = nullptr);
} // namespace mozilla::MacLaunchHelper
#endif // __OBJC__
extern "C" {
/**
* Passing an aPid parameter to LaunchChildMac will wait for the launched
@ -27,7 +17,6 @@ extern "C" {
* pid of the terminated process to confirm that it executed successfully.
*/
void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid = 0);
void LaunchMacApp(int aArgc, char** aArgv);
bool LaunchElevatedUpdate(int aArgc, char** aArgv, pid_t* aPid = 0);
bool InstallPrivilegedHelper();
void AbortElevatedUpdate();

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

@ -6,7 +6,6 @@
#include "MacLaunchHelper.h"
#include "MacAutoreleasePool.h"
#include "MacUtils.h"
#include "mozilla/UniquePtr.h"
#include <Cocoa/Cocoa.h>
@ -17,79 +16,6 @@
#include <stdio.h>
using namespace mozilla;
using namespace mozilla::MacUtils;
using namespace mozilla::MacLaunchHelper;
static void RegisterAppWithLaunchServices(NSString* aBundlePath) {
MacAutoreleasePool pool;
@try {
OSStatus status =
LSRegisterURL((CFURLRef)[NSURL fileURLWithPath:aBundlePath], YES);
if (status != noErr) {
NSLog(@"We failed to register the app in the Launch Services database, "
@"which may lead to a failure to launch the app. Launch path: %@",
aBundlePath);
}
} @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason);
}
}
static void StripQuarantineBit(NSString* aBundlePath) {
MacAutoreleasePool pool;
NSArray* arguments = @[ @"-dr", @"com.apple.quarantine", aBundlePath ];
LaunchTask(@"/usr/bin/xattr", arguments);
}
namespace mozilla::MacLaunchHelper {
void LaunchMacAppWithBundle(NSString* aBundlePath, NSArray* aArguments) {
MacAutoreleasePool pool;
@try {
NSString* launchPath = aBundlePath;
if (![launchPath hasSuffix:@".app"]) {
// We only support launching applications inside .app bundles.
NSLog(@"An attempt was made to launch an app that was not in a .app "
@"bundle. Please verify launch path: %@",
launchPath);
return;
}
StripQuarantineBit(launchPath);
RegisterAppWithLaunchServices(launchPath);
// We use NSWorkspace to register the application into the
// `TALAppsToRelaunchAtLogin` list and allow for macOS session resume.
// This API only works with `.app`s.
__block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSWorkspaceOpenConfiguration* config =
[NSWorkspaceOpenConfiguration configuration];
[config setArguments:aArguments];
[config setCreatesNewApplicationInstance:YES];
[config setEnvironment:[[NSProcessInfo processInfo] environment]];
[[NSWorkspace sharedWorkspace]
openApplicationAtURL:[NSURL fileURLWithPath:launchPath]
configuration:config
completionHandler:^(NSRunningApplication* aChild, NSError* aError) {
if (aError) {
NSLog(@"LaunchMacApp: Failed to run application. Error: %@",
aError);
}
dispatch_semaphore_signal(semaphore);
}];
// We use a semaphore to wait for the application to launch.
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
} @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason);
}
}
} // namespace mozilla::MacLaunchHelper
void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid) {
MacAutoreleasePool pool;
@ -100,32 +26,20 @@ void LaunchChildMac(int aArgc, char** aArgv, pid_t* aPid) {
for (int i = 1; i < aArgc; i++) {
[arguments addObject:[NSString stringWithUTF8String:aArgv[i]]];
}
NSTask* task = [[NSTask alloc] init];
[task setExecutableURL:[NSURL fileURLWithPath:launchPath]];
[task setArguments:arguments];
NSError* error = nil;
[task launchAndReturnError:&error];
if (!error && aPid) {
*aPid = [task processIdentifier];
[task waitUntilExit];
NSTask* child = [NSTask launchedTaskWithLaunchPath:launchPath
arguments:arguments];
if (aPid) {
*aPid = [child processIdentifier];
// We used to use waitpid to wait for the process to terminate. This is
// incompatible with NSTask and we wait for the process to exit here
// instead.
[child waitUntilExit];
}
[task release];
} @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason);
}
}
void LaunchMacApp(int aArgc, char** aArgv) {
MacAutoreleasePool pool;
NSString* launchPath = [NSString stringWithUTF8String:aArgv[0]];
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:aArgc - 1];
for (int i = 1; i < aArgc; i++) {
[arguments addObject:[NSString stringWithUTF8String:aArgv[i]]];
}
LaunchMacAppWithBundle(launchPath, arguments);
}
bool InstallPrivilegedHelper() {
AuthorizationRef authRef = NULL;
OSStatus status = AuthorizationCreate(
@ -156,9 +70,8 @@ bool InstallPrivilegedHelper() {
CFErrorRef cfError;
// This does all the work of verifying the helper tool against the
// application and vice-versa. Once verification has passed, the embedded
// launchd.plist is extracted and placed in /Library/LaunchDaemons and
// then loaded. The executable is placed in
// /Library/PrivilegedHelperTools.
// launchd.plist is extracted and placed in /Library/LaunchDaemons and then
// loaded. The executable is placed in /Library/PrivilegedHelperTools.
result = (BOOL)SMJobBless(kSMDomainSystemLaunchd,
(CFStringRef) @"org.mozilla.updater", authRef,
&cfError);

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

@ -13,9 +13,8 @@
#include <sys/mount.h>
#include <sys/param.h>
#include "MacLaunchHelper.h"
#include "MacRunFromDmgUtils.h"
#include "MacUtils.h"
#include "MacLaunchHelper.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/glean/GleanMetrics.h"
@ -38,9 +37,6 @@
// https://developer.apple.com/documentation/iokit
// https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/
using namespace mozilla::MacUtils;
using namespace mozilla::MacLaunchHelper;
namespace mozilla::MacRunFromDmgUtils {
/**
@ -263,6 +259,35 @@ static void ShowInstallFailedDialog() {
NS_OBJC_END_TRY_IGNORE_BLOCK;
}
/**
* Helper to launch macOS tasks via NSTask.
*/
static void LaunchTask(NSString* aPath, NSArray* aArguments) {
NSTask* task = [[NSTask alloc] init];
[task setExecutableURL:[NSURL fileURLWithPath:aPath]];
if (aArguments) {
[task setArguments:aArguments];
}
[task launchAndReturnError:nil];
[task release];
}
static void LaunchInstalledApp(NSString* aBundlePath) {
LaunchTask([[NSBundle bundleWithPath:aBundlePath] executablePath], nil);
}
static void RegisterAppWithLaunchServices(NSString* aBundlePath) {
NSArray* arguments = @[ @"-f", aBundlePath ];
LaunchTask(@"/System/Library/Frameworks/CoreServices.framework/Frameworks/"
@"LaunchServices.framework/Support/lsregister",
arguments);
}
static void StripQuarantineBit(NSString* aBundlePath) {
NSArray* arguments = @[ @"-d", @"com.apple.quarantine", aBundlePath ];
LaunchTask(@"/usr/bin/xattr", arguments);
}
#ifdef MOZ_UPDATER
bool LaunchElevatedDmgInstall(NSString* aBundlePath, NSArray* aArguments) {
NSTask* task = [[NSTask alloc] init];
@ -289,6 +314,8 @@ static bool InstallFromPath(NSString* aBundlePath, NSString* aDestPath) {
bool installSuccessful = false;
NSFileManager* fileManager = [NSFileManager defaultManager];
if ([fileManager copyItemAtPath:aBundlePath toPath:aDestPath error:nil]) {
RegisterAppWithLaunchServices(aDestPath);
StripQuarantineBit(aDestPath);
installSuccessful = true;
}
@ -457,7 +484,8 @@ bool MaybeInstallAndRelaunch() {
// a more sophisticated user intentionally running from .dmg.
if ([fileManager fileExistsAtPath:destPath]) {
if (AskUserIfWeShouldLaunchExistingInstall()) {
LaunchMacAppWithBundle(destPath);
StripQuarantineBit(destPath);
LaunchInstalledApp(destPath);
return true;
}
return false;
@ -472,7 +500,7 @@ bool MaybeInstallAndRelaunch() {
return false;
}
LaunchMacAppWithBundle(destPath);
LaunchInstalledApp(destPath);
return true;
}

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

@ -1,17 +0,0 @@
/* -*- 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/. */
#ifndef MacUtils_h_
#define MacUtils_h_
#include <Cocoa/Cocoa.h>
namespace mozilla::MacUtils {
void LaunchTask(NSString* aPath, NSArray* aArguments);
} // namespace mozilla::MacUtils
#endif

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

@ -1,32 +0,0 @@
/* -*- Mode: C++; tab-width: 4; 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 "MacAutoreleasePool.h"
#include "MacUtils.h"
namespace mozilla::MacUtils {
/**
* Helper to launch macOS tasks via NSTask and wait for the launched task to
* terminate.
*/
void LaunchTask(NSString* aPath, NSArray* aArguments) {
MacAutoreleasePool pool;
@try {
NSTask* task = [[NSTask alloc] init];
[task setExecutableURL:[NSURL fileURLWithPath:aPath]];
if (aArguments) {
[task setArguments:aArguments];
}
[task launchAndReturnError:nil];
[task waitUntilExit];
[task release];
} @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason);
}
}
} // namespace mozilla::MacUtils

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

@ -76,14 +76,12 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
EXPORTS.mozilla += [
"MacRunFromDmgUtils.h",
"MacUtils.h",
]
UNIFIED_SOURCES += [
"MacApplicationDelegate.mm",
"MacAutoreleasePool.mm",
"MacLaunchHelper.mm",
"MacRunFromDmgUtils.mm",
"MacUtils.mm",
"nsCommandLineServiceMac.mm",
"nsNativeAppSupportCocoa.mm",
"updaterfileutils_osx.mm",

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

@ -2530,7 +2530,7 @@ nsresult LaunchChild(bool aBlankCommandLine, bool aTryExec) {
# if defined(XP_MACOSX)
InitializeMacApp();
CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
LaunchMacApp(gRestartArgc, gRestartArgv);
LaunchChildMac(gRestartArgc, gRestartArgv);
# else
nsCOMPtr<nsIFile> lf;
nsresult rv = XRE_GetBinaryPath(getter_AddRefs(lf));

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

@ -42,42 +42,13 @@ void AddToCommandLine(const char* inArgText) {
// memory.
void SetupMacCommandLine(int& argc, char**& argv, bool forRestart) {
sArgs = static_cast<char**>(malloc(kArgsGrowSize * sizeof(char*)));
if (!sArgs) {
return;
}
if (!sArgs) return;
sArgsAllocated = kArgsGrowSize;
sArgs[0] = nullptr;
sArgsUsed = 0;
NSString* path = [NSString stringWithUTF8String:argv[0]];
// We adjust the path to point to the .app bundle, rather than the executable
// itself, to allow for the use of the NSWorkspace API for launching and
// relaunching the application. We intentionally exclude the
// org.mozilla.updater binary because we are experiencing NSCocoaErrors of
// type `kLSUnknownErr` when trying to launch the updater.app with the
// NSWorkspace API, at least on macOS 10.15. The updater is launched using
// NSTask instead. We do not experience these NSCocoaErrors on more modern
// versions of macOS and we may be able to switch to the NSWorkspace API once
// we no longer support the older versions of macOS where these errors occur.
// See bug 1911178.
if (![path hasSuffix:@"org.mozilla.updater"] && ![path hasSuffix:@".app"]) {
// Ensure that the path in the first argument points to the .app bundle.
// This strips three last path components, for example:
//
// Firefox.app/Contents/MacOS/firefox -> Firefox.app
//
path = [[[path stringByDeletingLastPathComponent]
stringByDeletingLastPathComponent] stringByDeletingLastPathComponent];
}
if (![path hasSuffix:@"org.mozilla.updater"] && ![path hasSuffix:@".app"]) {
// We were unable to obtain the path to the .app bundle and are unable to
// build a valid command line.
return;
}
AddToCommandLine(path.UTF8String);
// Copy the rest of the args, stripping anything we don't want.
for (int arg = 1; arg < argc; arg++) {
// Copy args, stripping anything we don't want.
for (int arg = 0; arg < argc; arg++) {
char* flag = argv[arg];
// Don't pass on the psn (Process Serial Number) flag from the OS, or
// the "-foreground" flag since it will be set below if necessary.

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

@ -362,9 +362,7 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
// appFilePath and workingDirPath are only used when the application will be
// restarted.
#ifndef XP_MACOSX
nsAutoCString appFilePath;
#endif
nsAutoCString workingDirPath;
if (restart) {
// Get the path to the current working directory.
@ -374,9 +372,7 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
}
// Get the application file path used by the updater to restart the
// application after the update has finished. Note that macOS uses the
// path to the application bundle, i.e. installDirPath, to relaunch the
// application.
// application after the update has finished.
nsCOMPtr<nsIFile> appFile;
XRE_GetBinaryPath(getter_AddRefs(appFile));
if (!appFile) {
@ -390,7 +386,7 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
return;
}
CopyUTF16toUTF8(appFilePathW, appFilePath);
#elif !defined(XP_MACOSX)
#else
rv = appFile->GetNativePath(appFilePath);
if (NS_FAILED(rv)) {
return;
@ -529,11 +525,7 @@ static void ApplyUpdate(nsIFile* greDir, nsIFile* updateDir, nsIFile* appDir,
argv[4] = (char*)pid.get();
if (restart && appArgc) {
argv[5] = (char*)workingDirPath.get();
#if defined(XP_MACOSX)
argv[6] = (char*)installDirPath.get();
#else
argv[6] = (char*)appFilePath.get();
#endif
for (int i = 1; i < appArgc; ++i) {
argv[6 + i] = appArgv[i];
}