Issue #1751 - Remove Mac code behind MOZ_WIDGET_TOOLKIT == 'cocoa'

This commit is contained in:
Moonchild 2021-06-21 17:52:42 +00:00 • committed by roytam1
commit ba00d14c12
382 changed files with 36 additions and 22824 deletions

View file

@ -14,16 +14,3 @@ endif
endif
include $(topsrcdir)/config/rules.mk
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
export::
sed -e 's/%MOZ_MACBUNDLE_ID%/$(MOZ_MACBUNDLE_ID)/' $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/bin/Info.plist
libs::
$(NSINSTALL) -D $(DIST)/bin/updater.app
rsync -a -C --exclude '*.in' $(srcdir)/macbuild/Contents $(DIST)/bin/updater.app
rsync -a -C $(DIST)/bin/Info.plist $(DIST)/bin/updater.app/Contents
sed -e 's/%APP_NAME%/$(MOZ_APP_DISPLAYNAME)/' $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | \
iconv -f UTF-8 -t UTF-16 > $(DIST)/bin/updater.app/Contents/Resources/English.lproj/InfoPlist.strings
$(NSINSTALL) -D $(DIST)/bin/updater.app/Contents/MacOS
$(NSINSTALL) $(DIST)/bin/org.mozilla.updater $(DIST)/bin/updater.app/Contents/MacOS
endif

View file

@ -1,384 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 <Cocoa/Cocoa.h>
#include <CoreServices/CoreServices.h>
#include <crt_externs.h>
#include <stdlib.h>
#include <stdio.h>
#include <spawn.h>
#include <SystemConfiguration/SystemConfiguration.h>
#include "readstrings.h"
class MacAutoreleasePool {
public:
MacAutoreleasePool()
{
mPool = [[NSAutoreleasePool alloc] init];
}
~MacAutoreleasePool()
{
[mPool release];
}
private:
NSAutoreleasePool* mPool;
};
void LaunchChild(int argc, const char** argv)
{
MacAutoreleasePool pool;
@try {
NSString* launchPath = [NSString stringWithUTF8String:argv[0]];
NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:argc - 1];
for (int i = 1; i < argc; i++) {
[arguments addObject:[NSString stringWithUTF8String:argv[i]]];
}
[NSTask launchedTaskWithLaunchPath:launchPath
arguments:arguments];
} @catch (NSException* e) {
NSLog(@"%@: %@", e.name, e.reason);
}
}
void
LaunchMacPostProcess(const char* aAppBundle)
{
MacAutoreleasePool pool;
// Launch helper to perform post processing for the update; this is the Mac
// analogue of LaunchWinPostProcess (PostUpdateWin).
NSString* iniPath = [NSString stringWithUTF8String:aAppBundle];
iniPath =
[iniPath stringByAppendingPathComponent:@"Contents/Resources/updater.ini"];
NSFileManager* fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:iniPath]) {
// the file does not exist; there is nothing to run
return;
}
int readResult;
char values[2][MAX_TEXT_LEN];
readResult = ReadStrings([iniPath UTF8String],
"ExeRelPath\0ExeArg\0",
2,
values,
"PostUpdateMac");
if (readResult) {
return;
}
NSString *exeRelPath = [NSString stringWithUTF8String:values[0]];
NSString *exeArg = [NSString stringWithUTF8String:values[1]];
if (!exeArg || !exeRelPath) {
return;
}
// The path must not traverse directories and it must be a relative path.
if ([exeRelPath rangeOfString:@".."].location != NSNotFound ||
[exeRelPath rangeOfString:@"./"].location != NSNotFound ||
[exeRelPath rangeOfString:@"/"].location == 0) {
return;
}
NSString* exeFullPath = [NSString stringWithUTF8String:aAppBundle];
exeFullPath = [exeFullPath stringByAppendingPathComponent:exeRelPath];
char optVals[1][MAX_TEXT_LEN];
readResult = ReadStrings([iniPath UTF8String],
"ExeAsync\0",
1,
optVals,
"PostUpdateMac");
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:exeFullPath];
[task setArguments:[NSArray arrayWithObject:exeArg]];
[task launch];
if (!readResult) {
NSString *exeAsync = [NSString stringWithUTF8String:optVals[0]];
if ([exeAsync isEqualToString:@"false"]) {
[task waitUntilExit];
}
}
// ignore the return value of the task, there's nothing we can do with it
[task release];
}
id ConnectToUpdateServer()
{
MacAutoreleasePool pool;
id updateServer = nil;
BOOL isConnected = NO;
int currTry = 0;
const int numRetries = 10; // Number of IPC connection retries before
// giving up.
while (!isConnected && currTry < numRetries) {
@try {
updateServer = (id)[NSConnection
rootProxyForConnectionWithRegisteredName:
@"org.mozilla.updater.server"
host:nil
usingNameServer:[NSSocketPortNameServer sharedInstance]];
if (!updateServer ||
![updateServer respondsToSelector:@selector(abort)] ||
![updateServer respondsToSelector:@selector(getArguments)] ||
![updateServer respondsToSelector:@selector(shutdown)]) {
NSLog(@"Server doesn't exist or doesn't provide correct selectors.");
sleep(1); // Wait 1 second.
currTry++;
} else {
isConnected = YES;
}
} @catch (NSException* e) {
NSLog(@"Encountered exception, retrying: %@: %@", e.name, e.reason);
sleep(1); // Wait 1 second.
currTry++;
}
}
if (!isConnected) {
NSLog(@"Failed to connect to update server after several retries.");
return nil;
}
return updateServer;
}
void CleanupElevatedMacUpdate(bool aFailureOccurred)
{
MacAutoreleasePool pool;
id updateServer = ConnectToUpdateServer();
if (updateServer) {
@try {
if (aFailureOccurred) {
[updateServer performSelector:@selector(abort)];
} else {
[updateServer performSelector:@selector(shutdown)];
}
} @catch (NSException* e) { }
}
NSFileManager* manager = [NSFileManager defaultManager];
[manager removeItemAtPath:@"/Library/PrivilegedHelperTools/org.mozilla.updater"
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 in launchctlArgs.
LaunchChild(3, launchctlArgs);
}
// Note: Caller is responsible for freeing argv.
bool ObtainUpdaterArguments(int* argc, char*** argv)
{
MacAutoreleasePool pool;
id updateServer = ConnectToUpdateServer();
if (!updateServer) {
// Let's try our best and clean up.
CleanupElevatedMacUpdate(true);
return false; // Won't actually get here due to CleanupElevatedMacUpdate.
}
@try {
NSArray* updaterArguments =
[updateServer performSelector:@selector(getArguments)];
*argc = [updaterArguments count];
char** tempArgv = (char**)malloc(sizeof(char*) * (*argc));
for (int i = 0; i < *argc; i++) {
int argLen = [[updaterArguments objectAtIndex:i] length] + 1;
tempArgv[i] = (char*)malloc(argLen);
strncpy(tempArgv[i], [[updaterArguments objectAtIndex:i] UTF8String],
argLen);
}
*argv = tempArgv;
} @catch (NSException* e) {
// Let's try our best and clean up.
CleanupElevatedMacUpdate(true);
return false; // Won't actually get here due to CleanupElevatedMacUpdate.
}
return true;
}
/**
* The ElevatedUpdateServer is launched from a non-elevated updater process.
* It allows an elevated updater process (usually a privileged helper tool) to
* connect to it and receive all the necessary arguments to complete a
* successful update.
*/
@interface ElevatedUpdateServer : NSObject
{
NSArray* mUpdaterArguments;
BOOL mShouldKeepRunning;
BOOL mAborted;
}
- (id)initWithArgs:(NSArray*)args;
- (BOOL)runServer;
- (NSArray*)getArguments;
- (void)abort;
- (BOOL)wasAborted;
- (void)shutdown;
- (BOOL)shouldKeepRunning;
@end
@implementation ElevatedUpdateServer
- (id)initWithArgs:(NSArray*)args
{
self = [super init];
if (!self) {
return nil;
}
mUpdaterArguments = args;
mShouldKeepRunning = YES;
mAborted = NO;
return self;
}
- (BOOL)runServer
{
NSPort* serverPort = [NSSocketPort port];
NSConnection* server = [NSConnection connectionWithReceivePort:serverPort
sendPort:serverPort];
[server setRootObject:self];
if ([server registerName:@"org.mozilla.updater.server"
withNameServer:[NSSocketPortNameServer sharedInstance]] == NO) {
NSLog(@"Unable to register as DirectoryServer.");
NSLog(@"Is another copy running?");
return NO;
}
while ([self shouldKeepRunning] &&
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate distantFuture]]);
return ![self wasAborted];
}
- (NSArray*)getArguments
{
return mUpdaterArguments;
}
- (void)abort
{
mAborted = YES;
[self shutdown];
}
- (BOOL)wasAborted
{
return mAborted;
}
- (void)shutdown
{
mShouldKeepRunning = NO;
}
- (BOOL)shouldKeepRunning
{
return mShouldKeepRunning;
}
@end
bool ServeElevatedUpdate(int argc, const char** argv)
{
MacAutoreleasePool pool;
NSMutableArray* updaterArguments = [NSMutableArray arrayWithCapacity:argc];
for (int i = 0; i < argc; i++) {
[updaterArguments addObject:[NSString stringWithUTF8String:argv[i]]];
}
ElevatedUpdateServer* updater =
[[ElevatedUpdateServer alloc] initWithArgs:[updaterArguments copy]];
bool didSucceed = [updater runServer];
[updater release];
return didSucceed;
}
bool IsOwnedByGroupAdmin(const char* aAppBundle)
{
MacAutoreleasePool pool;
NSString* appDir = [NSString stringWithUTF8String:aAppBundle];
NSFileManager* fileManager = [NSFileManager defaultManager];
NSDictionary* attributes = [fileManager attributesOfItemAtPath:appDir
error:nil];
bool isOwnedByAdmin = false;
if (attributes &&
[[attributes valueForKey:NSFileGroupOwnerAccountID] intValue] == 80) {
isOwnedByAdmin = true;
}
return isOwnedByAdmin;
}
void SetGroupOwnershipAndPermissions(const char* aAppBundle)
{
MacAutoreleasePool pool;
NSString* appDir = [NSString stringWithUTF8String:aAppBundle];
NSFileManager* fileManager = [NSFileManager defaultManager];
NSError* error = nil;
NSArray* paths =
[fileManager subpathsOfDirectoryAtPath:appDir
error:&error];
if (error) {
return;
}
// Set group ownership of Firefox.app to 80 ("admin") and permissions to
// 0775.
if (![fileManager setAttributes:@{ NSFileGroupOwnerAccountID: @(80),
NSFilePosixPermissions: @(0775) }
ofItemAtPath:appDir
error:&error] || error) {
return;
}
NSArray* permKeys = [NSArray arrayWithObjects:NSFileGroupOwnerAccountID,
NSFilePosixPermissions,
nil];
// For all descendants of Firefox.app, set group ownership to 80 ("admin") and
// ensure write permission for the group.
for (NSString* currPath in paths) {
NSString* child = [appDir stringByAppendingPathComponent:currPath];
NSDictionary* oldAttributes =
[fileManager attributesOfItemAtPath:child
error:&error];
if (error) {
return;
}
// Skip symlinks, since they could be pointing to files outside of the .app
// bundle.
if ([oldAttributes fileType] == NSFileTypeSymbolicLink) {
continue;
}
NSNumber* oldPerms =
(NSNumber*)[oldAttributes valueForKey:NSFilePosixPermissions];
NSArray* permObjects =
[NSArray arrayWithObjects:
[NSNumber numberWithUnsignedLong:80],
[NSNumber numberWithUnsignedLong:[oldPerms shortValue] | 020],
nil];
NSDictionary* attributes = [NSDictionary dictionaryWithObjects:permObjects
forKeys:permKeys];
if (![fileManager setAttributes:attributes
ofItemAtPath:child
error:&error] || error) {
return;
}
}
}

View file

@ -1,39 +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>CFBundleExecutable</key>
<string>org.mozilla.updater</string>
<key>CFBundleIconFile</key>
<string>updater.icns</string>
<key>CFBundleIdentifier</key>
<string>org.mozilla.updater</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSMinimumSystemVersion</key>
<string>10.5</string>
<key>LSMinimumSystemVersionByArchitecture</key>
<dict>
<key>i386</key>
<string>10.5.0</string>
<key>x86_64</key>
<string>10.6.0</string>
</dict>
<key>SMAuthorizedClients</key>
<array>
<string>identifier "%MOZ_MACBUNDLE_ID%" and ((anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9]) or (anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "43AQ936H96"))</string>
</array>
</dict>
</plist>

View file

@ -1,7 +0,0 @@
/* 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/. */
/* Localized versions of Info.plist keys */
CFBundleName = "%APP_NAME% Software Update";

View file

@ -1,19 +0,0 @@
{
IBClasses = (
{
CLASS = FirstResponder;
LANGUAGE = ObjC;
SUPERCLASS = NSObject;
},
{
CLASS = UpdaterUI;
LANGUAGE = ObjC;
OUTLETS = {
progressBar = NSProgressIndicator;
progressTextField = NSTextField;
};
SUPERCLASS = NSObject;
}
);
IBVersion = 1;
}

View file

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IBDocumentLocation</key>
<string>111 162 356 240 0 0 1440 878 </string>
<key>IBEditorPositions</key>
<dict>
<key>29</key>
<string>106 299 84 44 0 0 1440 878 </string>
</dict>
<key>IBFramework Version</key>
<string>489.0</string>
<key>IBOpenObjects</key>
<array>
<integer>21</integer>
<integer>29</integer>
</array>
<key>IBSystem Version</key>
<string>10J567</string>
</dict>
</plist>

View file

@ -3,26 +3,13 @@
# 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/.
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
Program('org.mozilla.updater')
else:
Program('updater')
Program('updater')
updater_rel_path = ''
include('updater-common.build')
CXXFLAGS += CONFIG['MOZ_BZ2_CFLAGS']
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
LDFLAGS += ['-sectcreate',
'__TEXT',
'__info_plist',
TOPOBJDIR + '/dist/bin/Info.plist',
'-sectcreate',
'__TEXT',
'__launchd_plist',
SRCDIR + '/Launchd.plist']
GENERATED_FILES = [
'primaryCert.h',
'secondaryCert.h',

View file

@ -1,144 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#import <Cocoa/Cocoa.h>
#include <stdio.h>
#include <unistd.h>
#include "mozilla/Sprintf.h"
#include "progressui.h"
#include "readstrings.h"
#include "errors.h"
#define TIMER_INTERVAL 0.2
static float sProgressVal; // between 0 and 100
static BOOL sQuit = NO;
static BOOL sIndeterminate = NO;
static StringTable sLabels;
static const char *sUpdatePath;
@interface UpdaterUI : NSObject
{
IBOutlet NSProgressIndicator *progressBar;
IBOutlet NSTextField *progressTextField;
}
@end
@implementation UpdaterUI
-(void)awakeFromNib
{
NSWindow *w = [progressBar window];
[w setTitle:[NSString stringWithUTF8String:sLabels.title]];
[progressTextField setStringValue:[NSString stringWithUTF8String:sLabels.info]];
NSRect origTextFrame = [progressTextField frame];
[progressTextField sizeToFit];
int widthAdjust = progressTextField.frame.size.width - origTextFrame.size.width;
if (widthAdjust > 0) {
NSRect f;
f.size.width = w.frame.size.width + widthAdjust;
f.size.height = w.frame.size.height;
[w setFrame:f display:YES];
}
[w center];
[progressBar setIndeterminate:sIndeterminate];
[progressBar setDoubleValue:0.0];
[[NSTimer scheduledTimerWithTimeInterval:TIMER_INTERVAL target:self
selector:@selector(updateProgressUI:)
userInfo:nil repeats:YES] retain];
// Make sure we are on top initially
[NSApp activateIgnoringOtherApps:YES];
}
// called when the timer goes off
-(void)updateProgressUI:(NSTimer *)aTimer
{
if (sQuit) {
[aTimer invalidate];
[aTimer release];
// It seems to be necessary to activate and hide ourselves before we stop,
// otherwise the "run" method will not return until the user focuses some
// other app. The activate step is necessary if we are not the active app.
// This is a big hack, but it seems to do the trick.
[NSApp activateIgnoringOtherApps:YES];
[NSApp hide:self];
[NSApp stop:self];
}
float progress = sProgressVal;
[progressBar setDoubleValue:(double)progress];
}
// leave this as returning a BOOL instead of NSApplicationTerminateReply
// for backward compatibility
- (BOOL)applicationShouldTerminate:(NSApplication *)sender
{
return sQuit;
}
@end
int
InitProgressUI(int *pargc, char ***pargv)
{
sUpdatePath = (*pargv)[1];
return 0;
}
int
ShowProgressUI(bool indeterminate)
{
// Only show the Progress UI if the process is taking a significant amount of
// time where a significant amount of time is defined as .5 seconds after
// ShowProgressUI is called sProgress is less than 70.
usleep(500000);
if (sQuit || sProgressVal > 70.0f)
return 0;
char path[PATH_MAX];
SprintfLiteral(path, "%s/updater.ini", sUpdatePath);
if (ReadStrings(path, &sLabels) != OK)
return -1;
// Continue the update without showing the Progress UI if any of the supplied
// strings are larger than MAX_TEXT_LEN (Bug 628829).
if (!(strlen(sLabels.title) < MAX_TEXT_LEN - 1 &&
strlen(sLabels.info) < MAX_TEXT_LEN - 1))
return -1;
sIndeterminate = indeterminate;
[NSApplication sharedApplication];
[NSBundle loadNibNamed:@"MainMenu" owner:NSApp];
[NSApp run];
return 0;
}
// Called on a background thread
void
QuitProgressUI()
{
sQuit = YES;
}
// Called on a background thread
void
UpdateProgressUI(float progress)
{
sProgressVal = progress; // 32-bit writes are atomic
}

View file

@ -72,24 +72,6 @@ if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
'progressui_gtk.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
have_progressui = 1
srcs += [
'launchchild_osx.mm',
'progressui_osx.mm',
]
OS_LIBS += [
'-framework Cocoa',
'-framework Security',
'-framework SystemConfiguration',
]
UNIFIED_SOURCES += [
'/toolkit/xre/updaterfileutils_osx.mm',
]
LOCAL_INCLUDES += [
'/toolkit/xre',
]
if have_progressui == 0:
srcs += [
'progressui_null.cpp',