Backed out changeset b55cdb5c3841 (bug 1728167) for causing xpcshell failures in bootstrapSvc.js

CLOSED TREE
This commit is contained in:
Alexandru Michis 2021-09-03 02:56:46 +03:00
Родитель 5b0ce631d6
Коммит 0ffe70c46e
6 изменённых файлов: 945 добавлений и 1086 удалений

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

@ -450,59 +450,3 @@ void SetGroupOwnershipAndPermissions(const char* aAppBundle) {
}
}
}
#if !defined(MAC_OS_X_VERSION_10_13) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13
@interface NSTask (NSTask10_13)
@property(copy) NSURL* executableURL NS_AVAILABLE_MAC(10_13);
@property(copy) NSArray<NSString*>* arguments;
- (BOOL)launchAndReturnError:(NSError**)error NS_AVAILABLE_MAC(10_13);
@end
#endif
/**
* Helper to launch macOS tasks via NSTask.
*/
static void LaunchTask(NSString* aPath, NSArray* aArguments) {
if (@available(macOS 10.13, *)) {
NSTask* task = [[NSTask alloc] init];
[task setExecutableURL:[NSURL fileURLWithPath:aPath]];
if (aArguments) {
[task setArguments:aArguments];
}
[task launchAndReturnError:nil];
[task release];
} else {
NSArray* arguments = aArguments;
if (!arguments) {
arguments = @[];
}
[NSTask launchedTaskWithLaunchPath:aPath arguments:arguments];
}
}
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) {
return false;
}
NSString* bundlePath = [NSString stringWithUTF8String:argv[2]];
NSString* destPath = [NSString stringWithUTF8String:argv[3]];
if ([[NSFileManager defaultManager] copyItemAtPath:bundlePath toPath:destPath error:nil]) {
RegisterAppWithLaunchServices(destPath);
StripQuarantineBit(destPath);
return true;
}
return false;
}

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

@ -80,7 +80,6 @@ void LaunchMacPostProcess(const char* aAppBundle);
bool ObtainUpdaterArguments(int* argc, char*** argv);
bool ServeElevatedUpdate(int argc, const char** argv);
void SetGroupOwnershipAndPermissions(const char* aAppBundle);
bool PerformInstallationFromDMG(int argc, char** argv);
struct UpdateServerThreadArgs {
int argc;
const NS_tchar** argv;
@ -2728,10 +2727,6 @@ int NS_main(int argc, NS_tchar** argv) {
// argument prior to callbackIndex is the working directory.
const int callbackIndex = 6;
// `isDMGInstall` is only ever true for macOS, but we are declaring it here
// to avoid a ton of extra #ifdef's.
bool isDMGInstall = false;
#ifdef XP_MACOSX
// We want to control file permissions explicitly, or else we could end up
// corrupting installs for other users on the system. Accordingly, set the
@ -2749,39 +2744,17 @@ int NS_main(int argc, NS_tchar** argv) {
return 1;
}
}
if (argc == 4 && (strstr(argv[1], "-dmgInstall") != 0)) {
isDMGInstall = true;
if (isElevated) {
PerformInstallationFromDMG(argc, argv);
freeArguments(argc, argv);
CleanupElevatedMacUpdate(true);
return 0;
}
}
#endif
#ifdef XP_WIN
NS_tchar elevatedLockFilePath[MAXPATHLEN] = {NS_T('\0')};
NS_tsnprintf(elevatedLockFilePath,
sizeof(elevatedLockFilePath) / sizeof(elevatedLockFilePath[0]),
NS_T("%s\\update_elevated.lock"), gPatchDirPath);
gUseSecureOutputPath =
sUsingService || (NS_tremove(elevatedLockFilePath) && errno != ENOENT);
#endif
if (!isDMGInstall) {
// Skip update-related code path for DMG installs.
#if defined(MOZ_VERIFY_MAR_SIGNATURE) && !defined(XP_WIN) && !defined(XP_MACOSX)
// On Windows and Mac we rely on native APIs to do verifications so we don't
// need to initialize NSS at all there.
// Otherwise, minimize the amount of NSS we depend on by avoiding all the
// NSS databases.
// Otherwise, minimize the amount of NSS we depend on by avoiding all the NSS
// databases.
if (NSS_NoDB_Init(nullptr) != SECSuccess) {
PRErrorCode error = PR_GetError();
fprintf(stderr, "Could not initialize NSS: %s (%d)",
PR_ErrorToName(error), (int)error);
fprintf(stderr, "Could not initialize NSS: %s (%d)", PR_ErrorToName(error),
(int)error);
_exit(1);
}
#endif
@ -2797,17 +2770,17 @@ int NS_main(int argc, NS_tchar** argv) {
// To process an update the updater command line must at a minimum have the
// directory path containing the updater.mar file to process as the first
// argument, the install directory as the second argument, and the directory
// to apply the update to as the third argument. When the updater is
// launched by another process the PID of the parent process should be
// provided in the optional fourth argument and the updater will wait on the
// parent process to exit if the value is non-zero and the process is
// present. This is necessary due to not being able to update files that are
// in use on Windows. The optional fifth argument is the callback's working
// directory and the optional sixth argument is the callback path. The
// callback is the application to launch after updating and it will be
// launched when these arguments are provided whether the update was
// successful or not. All remaining arguments are optional and are passed to
// the callback when it is launched.
// to apply the update to as the third argument. When the updater is launched
// by another process the PID of the parent process should be provided in the
// optional fourth argument and the updater will wait on the parent process to
// exit if the value is non-zero and the process is present. This is necessary
// due to not being able to update files that are in use on Windows. The
// optional fifth argument is the callback's working directory and the
// optional sixth argument is the callback path. The callback is the
// application to launch after updating and it will be launched when these
// arguments are provided whether the update was successful or not. All
// remaining arguments are optional and are passed to the callback when it is
// launched.
if (argc < 4) {
fprintf(stderr,
"Usage: updater patch-dir install-dir apply-to-dir [wait-pid "
@ -2853,6 +2826,15 @@ int NS_main(int argc, NS_tchar** argv) {
NS_tstrncpy(gPatchDirPath, argv[1], MAXPATHLEN);
gPatchDirPath[MAXPATHLEN - 1] = NS_T('\0');
#ifdef XP_WIN
NS_tchar elevatedLockFilePath[MAXPATHLEN] = {NS_T('\0')};
NS_tsnprintf(elevatedLockFilePath,
sizeof(elevatedLockFilePath) / sizeof(elevatedLockFilePath[0]),
NS_T("%s\\update_elevated.lock"), gPatchDirPath);
gUseSecureOutputPath =
sUsingService || (NS_tremove(elevatedLockFilePath) && errno != ENOENT);
#endif
// This check is also performed in workmonitor.cpp since the maintenance
// service can be called directly.
if (!IsValidFullPath(argv[2])) {
@ -2869,9 +2851,6 @@ int NS_main(int argc, NS_tchar** argv) {
#endif
return 1;
}
} // if (!isDMGInstall)
// The directory we're going to update to.
// We copy this string because we need to remove trailing slashes. The C++
// standard says that it's always safe to write to strings pointed to by argv
@ -2887,10 +2866,7 @@ int NS_main(int argc, NS_tchar** argv) {
bool useService = false;
bool testOnlyFallbackKeyExists = false;
bool noServiceFallback = false;
#endif
if (!isDMGInstall) {
#ifdef XP_WIN
// We never want the service to be used unless we build with
// the maintenance service.
# ifdef MOZ_MAINTENANCE_SERVICE
@ -2924,8 +2900,6 @@ int NS_main(int argc, NS_tchar** argv) {
}
#endif
} // if (!isDMGInstall)
// If there is a PID specified and it is not '0' then wait for the process to
// exit.
NS_tpid pid = 0;
@ -2942,7 +2916,6 @@ int NS_main(int argc, NS_tchar** argv) {
}
}
if (!isDMGInstall) {
// This check is also performed in workmonitor.cpp since the maintenance
// service can be called directly.
if (!IsValidFullPath(argv[3])) {
@ -2961,8 +2934,8 @@ int NS_main(int argc, NS_tchar** argv) {
}
// The directory we're going to update to.
// We copy this string because we need to remove trailing slashes. The C++
// standard says that it's always safe to write to strings pointed to by
// argv elements, but I don't necessarily believe it.
// standard says that it's always safe to write to strings pointed to by argv
// elements, but I don't necessarily believe it.
NS_tstrncpy(gWorkingDirPath, argv[3], MAXPATHLEN);
gWorkingDirPath[MAXPATHLEN - 1] = NS_T('\0');
slash = NS_tstrrchr(gWorkingDirPath, NS_SLASH);
@ -3008,12 +2981,10 @@ int NS_main(int argc, NS_tchar** argv) {
ShouldRunSilently(argc - callbackIndex, argv + callbackIndex);
}
} // if (!isDMGInstall)
#ifdef XP_MACOSX
if (!isElevated && (!IsRecursivelyWritable(argv[2]) || isDMGInstall)) {
// If the app directory isn't recursively writeable or if this is a DMG
// install, an elevated helper process is required.
if (!isElevated && !IsRecursivelyWritable(argv[2])) {
// If the app directory isn't recursively writeable, an elevated update is
// required.
if (sUpdateSilently) {
// An elevated update always requires an elevation dialog, so if we are
// updating silently, don't do an elevated update.
@ -3037,10 +3008,8 @@ int NS_main(int argc, NS_tchar** argv) {
if (t1.Run(ServeElevatedUpdateThreadFunc, &threadArgs) == 0) {
// Show an indeterminate progress bar while an elevated update is in
// progress.
if (!isDMGInstall) {
ShowProgressUI(true);
}
}
t1.Join();
}
@ -3049,11 +3018,6 @@ int NS_main(int argc, NS_tchar** argv) {
}
#endif
#ifdef XP_WIN
HANDLE updateLockFileHandle = INVALID_HANDLE_VALUE;
#endif
if (!isDMGInstall) {
NS_tchar logFilePath[MAXPATHLEN + 1] = {L'\0'};
#ifdef XP_WIN
if (gUseSecureOutputPath) {
@ -3169,13 +3133,13 @@ int NS_main(int argc, NS_tchar** argv) {
// used, in case of an error when fallback is not enabled we write the
// error to the update.status file.
// When fallback is disabled (MOZ_NO_SERVICE_FALLBACK does not exist) then
// we will instead fallback to not using the service and display a UAC
// prompt.
// we will instead fallback to not using the service and display a UAC prompt.
int lastFallbackError = FALLBACKKEY_UNKNOWN_ERROR;
// Check whether a second instance of the updater should be launched by the
// maintenance service or with the 'runas' verb when write access is denied
// to the installation directory.
// maintenance service or with the 'runas' verb when write access is denied to
// the installation directory.
HANDLE updateLockFileHandle = INVALID_HANDLE_VALUE;
if (!sUsingService &&
(argc > callbackIndex || sStagedUpdate || sReplaceRequest)) {
NS_tchar updateLockFilePath[MAXPATHLEN];
@ -3184,8 +3148,7 @@ int NS_main(int argc, NS_tchar** argv) {
// <install_dir>\updated.update_in_progress.lock
NS_tsnprintf(updateLockFilePath,
sizeof(updateLockFilePath) / sizeof(updateLockFilePath[0]),
NS_T("%s/updated.update_in_progress.lock"),
gInstallDirPath);
NS_T("%s/updated.update_in_progress.lock"), gInstallDirPath);
} else if (sReplaceRequest) {
// When processing a replace request, the lock file is:
// <install_dir>\..\moz_update_in_progress.lock
@ -3251,9 +3214,9 @@ int NS_main(int argc, NS_tchar** argv) {
return 1;
}
elevatedFileHandle = CreateFileW(
elevatedLockFilePath, GENERIC_READ | GENERIC_WRITE, 0, nullptr,
OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, nullptr);
elevatedFileHandle =
CreateFileW(elevatedLockFilePath, GENERIC_READ | GENERIC_WRITE, 0,
nullptr, OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, nullptr);
if (elevatedFileHandle == INVALID_HANDLE_VALUE) {
LOG(("Unable to create elevated lock file! Exiting"));
output_finish();
@ -3348,12 +3311,12 @@ int NS_main(int argc, NS_tchar** argv) {
// If the command was launched then wait for the service to be done.
if (useService) {
bool showProgressUI = false;
// Never show the progress UI when staging updates or in a
// background task.
// Never show the progress UI when staging updates or in a background
// task.
if (!sStagedUpdate && !sUpdateSilently) {
// We need to call this separately instead of allowing
// ShowProgressUI to initialize the strings because the service
// will move the ini file out of the way when running updater.
// ShowProgressUI to initialize the strings because the service will
// move the ini file out of the way when running updater.
showProgressUI = !InitProgressUIStrings();
}
@ -3442,8 +3405,8 @@ int NS_main(int argc, NS_tchar** argv) {
// determine if the updater has created a new one.
char uuidStringBefore[UUID_LEN] = {'\0'};
bool checkID = GetSecureID(uuidStringBefore);
// Write a catchall failure status in case it fails without changing
// the status.
// Write a catchall failure status in case it fails without changing the
// status.
WriteStatusFile(UPDATE_STATUS_UNCHANGED);
SHELLEXECUTEINFO sinfo;
@ -3477,9 +3440,9 @@ int NS_main(int argc, NS_tchar** argv) {
} else {
// Don't copy the secure output files if the elevation request was
// canceled since the status file written below is in the patch
// directory. At this point it should already be set to false and
// this is set here to make it clear that it should be false at this
// point and to prevent future changes from regressing this code.
// directory. At this point it should already be set to false and this
// is set here to make it clear that it should be false at this point
// and to prevent future changes from regressing this code.
gCopyOutputFiles = false;
WriteStatusFile(ELEVATION_CANCELED);
}
@ -3488,9 +3451,9 @@ int NS_main(int argc, NS_tchar** argv) {
// If we started the elevated updater, and it finished, check the secure
// update status file to make sure that it succeeded, and if it did we
// need to launch the PostUpdate process in the unelevated updater which
// is running in the current user's session. Note that we don't need to
// do this when staging an update since the PostUpdate step runs during
// the replace request.
// is running in the current user's session. Note that we don't need to do
// this when staging an update since the PostUpdate step runs during the
// replace request.
if (!sStagedUpdate) {
bool updateStatusSucceeded = false;
if (IsSecureUpdateStatusSucceeded(updateStatusSucceeded) &&
@ -3530,9 +3493,9 @@ int NS_main(int argc, NS_tchar** argv) {
}
return 0;
// This is the end of the code block for launching another instance of
// the updater using either the maintenance service or with the 'runas'
// verb when the updater doesn't have write access to the installation
// This is the end of the code block for launching another instance of the
// updater using either the maintenance service or with the 'runas' verb
// when the updater doesn't have write access to the installation
// directory.
}
// This is the end of the code block when the updater was not launched by
@ -3540,8 +3503,7 @@ int NS_main(int argc, NS_tchar** argv) {
// installation directory.
}
// If we made it this far this is the updater instance that will perform the
// actual update and gCopyOutputFiles will be false (e.g. the default
// value).
// actual update and gCopyOutputFiles will be false (e.g. the default value).
#endif
if (sStagedUpdate) {
@ -3556,15 +3518,15 @@ int NS_main(int argc, NS_tchar** argv) {
CloseHandle(updateLockFileHandle);
}
# endif
// WRITE_ERROR is one of the cases where the staging failure falls back
// to applying the update on startup.
// WRITE_ERROR is one of the cases where the staging failure falls back to
// applying the update on startup.
WriteStatusFile(WRITE_ERROR);
output_finish();
return 0;
}
#endif
// When staging updates, blow away the old installation directory and
// create it from scratch.
// When staging updates, blow away the old installation directory and create
// it from scratch.
ensure_remove_recursive(gWorkingDirPath);
}
if (!sReplaceRequest) {
@ -3601,10 +3563,10 @@ int NS_main(int argc, NS_tchar** argv) {
HANDLE callbackFile = INVALID_HANDLE_VALUE;
if (argc > callbackIndex) {
// If the callback executable is specified it must exist for a successful
// update. It is important we null out the whole buffer here because
// later we make the assumption that the callback application is inside
// the apply-to dir. If we don't have a fully null'ed out buffer it can
// lead to stack corruption which causes crashes and other problems.
// update. It is important we null out the whole buffer here because later
// we make the assumption that the callback application is inside the
// apply-to dir. If we don't have a fully null'ed out buffer it can lead
// to stack corruption which causes crashes and other problems.
NS_tchar callbackLongPath[MAXPATHLEN];
ZeroMemory(callbackLongPath, sizeof(callbackLongPath));
NS_tchar* targetPath = argv[callbackIndex];
@ -3664,8 +3626,8 @@ int NS_main(int argc, NS_tchar** argv) {
++s;
}
// Copy the string and replace backslashes with forward slashes along
// the way.
// Copy the string and replace backslashes with forward slashes along the
// way.
do {
if (*s == NS_T('\\')) {
*d = NS_T('/');
@ -3697,8 +3659,7 @@ int NS_main(int argc, NS_tchar** argv) {
return 1;
}
// Make a copy of the callback executable so it can be read when
// patching.
// Make a copy of the callback executable so it can be read when patching.
if (!CopyFileW(argv[callbackIndex], gCallbackBackupPath, false)) {
DWORD copyFileError = GetLastError();
if (copyFileError == ERROR_ACCESS_DENIED) {
@ -3750,8 +3711,8 @@ int NS_main(int argc, NS_tchar** argv) {
// Fail the update if the last error was not a sharing violation.
if (lastWriteError != ERROR_SHARING_VIOLATION) {
LOG((
"NS_main: callback app file in use, failed to exclusively open "
LOG(
("NS_main: callback app file in use, failed to exclusively open "
"executable file: " LOG_S,
argv[callbackIndex]));
if (lastWriteError == ERROR_ACCESS_DENIED) {
@ -3764,12 +3725,12 @@ int NS_main(int argc, NS_tchar** argv) {
}
// Fail even on sharing violation from a background task, since a
// background task has a higher risk of interfering with a running
// app. Note that this does not apply when staging (when an exclusive
// lock isn't necessary), as there is no callback.
// background task has a higher risk of interfering with a running app.
// Note that this does not apply when staging (when an exclusive lock
// isn't necessary), as there is no callback.
if (lastWriteError == ERROR_SHARING_VIOLATION && sUpdateSilently) {
LOG((
"NS_main: callback app file in use, failed to exclusively open "
LOG(
("NS_main: callback app file in use, failed to exclusively open "
"executable file from background task: " LOG_S,
argv[callbackIndex]));
WriteStatusFile(WRITE_ERROR_BACKGROUND_TASK_SHARING_VIOLATION);
@ -3786,8 +3747,8 @@ int NS_main(int argc, NS_tchar** argv) {
}
output_finish();
EXIT_WHEN_ELEVATED(elevatedLockFilePath, updateLockFileHandle, 1);
LaunchCallbackApp(argv[5], argc - callbackIndex,
argv + callbackIndex, sUsingService);
LaunchCallbackApp(argv[5], argc - callbackIndex, argv + callbackIndex,
sUsingService);
return 1;
}
@ -3803,12 +3764,12 @@ int NS_main(int argc, NS_tchar** argv) {
// request; it can be used during a replace request but then it doesn't
// use gDeleteDirPath.
if (!sStagedUpdate && !sReplaceRequest) {
// The directory to move files that are in use to on Windows. This
// directory will be deleted after the update is finished, on OS reboot
// using MoveFileEx if it contains files that are in use, or by the post
// update process after the update finishes. On Windows when performing a
// normal update (e.g. the update is not a staged update and is not a
// replace request) gWorkingDirPath is the same as gInstallDirPath and
// The directory to move files that are in use to on Windows. This directory
// will be deleted after the update is finished, on OS reboot using
// MoveFileEx if it contains files that are in use, or by the post update
// process after the update finishes. On Windows when performing a normal
// update (e.g. the update is not a staged update and is not a replace
// request) gWorkingDirPath is the same as gInstallDirPath and
// gWorkingDirPath is used because it is the destination directory.
NS_tsnprintf(gDeleteDirPath,
sizeof(gDeleteDirPath) / sizeof(gDeleteDirPath[0]),
@ -3822,8 +3783,8 @@ int NS_main(int argc, NS_tchar** argv) {
// Run update process on a background thread. ShowProgressUI may return
// before QuitProgressUI has been called, so wait for UpdateThreadFunc to
// terminate. Avoid showing the progress UI when staging an update, or if
// this is an elevated process on OSX.
// terminate. Avoid showing the progress UI when staging an update, or if this
// is an elevated process on OSX.
Thread t;
if (t.Run(UpdateThreadFunc, nullptr) == 0) {
if (!sStagedUpdate && !sReplaceRequest && !sUpdateSilently
@ -3851,18 +3812,17 @@ int NS_main(int argc, NS_tchar** argv) {
}
if (!sStagedUpdate && !sReplaceRequest && _wrmdir(gDeleteDirPath)) {
LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d",
DELETE_DIR, errno));
LOG(("NS_main: unable to remove directory: " LOG_S ", err: %d", DELETE_DIR,
errno));
// The directory probably couldn't be removed due to it containing files
// that are in use and will be removed on OS reboot. The call to remove
// the directory on OS reboot is done after the calls to remove the files
// so the files are removed first on OS reboot since the directory must be
// empty for the directory removal to be successful. The MoveFileEx call
// to remove the directory on OS reboot will fail if the process doesn't
// have write access to the HKEY_LOCAL_MACHINE registry key but this is ok
// since the installer / uninstaller will delete the directory along with
// its contents after an update is applied, on reinstall, and on
// uninstall.
// that are in use and will be removed on OS reboot. The call to remove the
// directory on OS reboot is done after the calls to remove the files so the
// files are removed first on OS reboot since the directory must be empty
// for the directory removal to be successful. The MoveFileEx call to remove
// the directory on OS reboot will fail if the process doesn't have write
// access to the HKEY_LOCAL_MACHINE registry key but this is ok since the
// installer / uninstaller will delete the directory along with its contents
// after an update is applied, on reinstall, and on uninstall.
if (MoveFileEx(gDeleteDirPath, nullptr, MOVEFILE_DELAY_UNTIL_REBOOT)) {
LOG(("NS_main: directory will be removed on OS reboot: " LOG_S,
DELETE_DIR));
@ -3875,8 +3835,6 @@ int NS_main(int argc, NS_tchar** argv) {
}
#endif /* XP_WIN */
} // if (!isDMGInstall)
#ifdef XP_MACOSX
if (isElevated) {
SetGroupOwnershipAndPermissions(gInstallDirPath);

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

@ -13,7 +13,6 @@
#include <sys/param.h>
#include "MacRunFromDmgUtils.h"
#include "MacLaunchHelper.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/intl/Localization.h"
@ -26,13 +25,19 @@
#include "nsIMacDockSupport.h"
#include "nsObjCExceptions.h"
#include "nsString.h"
#include "nsUpdateDriver.h"
#include "SDKDeclarations.h"
// For IOKit docs, see:
// https://developer.apple.com/documentation/iokit
// https://developer.apple.com/library/archive/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/
#if !defined(MAC_OS_X_VERSION_10_13) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13
@interface NSTask (NSTask10_13)
@property(copy) NSURL* executableURL NS_AVAILABLE_MAC(10_13);
@property(copy) NSArray<NSString*>* arguments;
- (BOOL)launchAndReturnError:(NSError**)error NS_AVAILABLE_MAC(10_13);
@end
#endif
namespace mozilla {
namespace MacRunFromDmgUtils {
@ -173,41 +178,11 @@ static void StripQuarantineBit(NSString* aBundlePath) {
LaunchTask(@"/usr/bin/xattr", arguments);
}
bool LaunchElevatedDmgInstall(NSString* aBundlePath, NSArray* aArguments) {
NSTask* task;
if (@available(macOS 10.13, *)) {
task = [[NSTask alloc] init];
[task setExecutableURL:[NSURL fileURLWithPath:aBundlePath]];
if (aArguments) {
[task setArguments:aArguments];
}
[task launchAndReturnError:nil];
} else {
NSArray* arguments = aArguments;
if (!arguments) {
arguments = @[];
}
task = [NSTask launchedTaskWithLaunchPath:aBundlePath arguments:arguments];
}
bool didSucceed = InstallPrivilegedHelper();
[task waitUntilExit];
if (@available(macOS 10.13, *)) {
[task release];
}
if (!didSucceed) {
AbortElevatedUpdate();
}
return didSucceed;
}
// Note: both arguments are expected to contain the app name (to end with
// '.app').
static bool InstallFromDmg(NSString* aBundlePath, NSString* aDestPath) {
bool installSuccessful = false;
NSFileManager* fileManager = [NSFileManager defaultManager];
if ([fileManager copyItemAtPath:aBundlePath toPath:aDestPath error:nil]) {
if ([[NSFileManager defaultManager] copyItemAtPath:aBundlePath toPath:aDestPath error:nil]) {
RegisterAppWithLaunchServices(aDestPath);
StripQuarantineBit(aDestPath);
installSuccessful = true;
@ -215,22 +190,10 @@ static bool InstallFromDmg(NSString* aBundlePath, NSString* aDestPath) {
// The installation may have been unsuccessful if the user did not have the
// rights to write to the Applications directory. Check for this situation and
// launch an elevated installation if necessary. Rather than creating a new,
// dedicated executable for this installation and incurring the
// added maintenance burden of yet another executable, we are using the
// updater binary. Since bug 394984 landed, the updater has the ability to
// install and launch itself as a Privileged Helper tool, which is what is
// necessary here.
// launch an elevated installation if necessary.
NSString* destDir = [aDestPath stringByDeletingLastPathComponent];
if (!installSuccessful && ![fileManager isWritableFileAtPath:destDir]) {
NSString* updaterBinPath = [NSString pathWithComponents:@[
aBundlePath, @"Contents", @"MacOS", [NSString stringWithUTF8String:UPDATER_APP], @"Contents",
@"MacOS", [NSString stringWithUTF8String:UPDATER_BIN]
]];
NSArray* arguments = @[ @"-dmgInstall", aBundlePath, aDestPath ];
LaunchElevatedDmgInstall(updaterBinPath, arguments);
installSuccessful = [fileManager fileExistsAtPath:aDestPath];
if (!installSuccessful && ![[NSFileManager defaultManager] isWritableFileAtPath:destDir]) {
// TODO: launch elevated installation.
}
if (!installSuccessful) {

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

@ -64,6 +64,16 @@ static LazyLogModule sUpdateLog("updatedriver");
#endif
#define LOG(args) MOZ_LOG(sUpdateLog, mozilla::LogLevel::Debug, args)
#ifdef XP_WIN
# define UPDATER_BIN "updater.exe"
# define MAINTENANCE_SVC_NAME L"MozillaMaintenance"
#elif XP_MACOSX
# define UPDATER_APP "updater.app"
# define UPDATER_BIN "org.mozilla.updater"
#else
# define UPDATER_BIN "updater"
#endif
#ifdef XP_MACOSX
static void UpdateDriverSetupMacCommandLine(int& argc, char**& argv,
bool restart) {

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

@ -26,16 +26,6 @@ typedef pid_t ProcessType;
typedef PRProcess* ProcessType;
#endif
#ifdef XP_WIN
# define UPDATER_BIN "updater.exe"
# define MAINTENANCE_SVC_NAME L"MozillaMaintenance"
#elif XP_MACOSX
# define UPDATER_APP "updater.app"
# define UPDATER_BIN "org.mozilla.updater"
#else
# define UPDATER_BIN "updater"
#endif
/**
* This function processes any available updates. As part of that process, it
* may exit the current process and relaunch it at a later time.

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

@ -30,12 +30,6 @@ using NSAppearanceName = NSString*;
@property(class, strong, readonly) NSColor* systemPurpleColor NS_AVAILABLE_MAC(10_10);
@end
@interface NSTask (NSTask10_13)
@property(copy) NSURL* executableURL NS_AVAILABLE_MAC(10_13);
@property(copy) NSArray<NSString*>* arguments;
- (BOOL)launchAndReturnError:(NSError**)error NS_AVAILABLE_MAC(10_13);
@end
#endif
#if !defined(MAC_OS_X_VERSION_10_14) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_14