Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

XPC service for Lion Sandboxing #165

Closed
wants to merge 1 commit into
from
Jump to file or symbol
Failed to load files and symbols.
+407 −3
Split
@@ -0,0 +1,5 @@
+// Sandbox Service only
+
+PRODUCT_NAME = com.andymatuschak.Sparkle.SandboxService
+WRAPPER_EXTENSION = xpc
+MACH_O_TYPE = mh_execute
@@ -0,0 +1,5 @@
+#include "ConfigCommon.xcconfig"
+#include "ConfigCommonDebug.xcconfig"
+#include "ConfigService.xcconfig"
+
+OTHER_CFLAGS = -fsingle-precision-constant -DDEBUG
@@ -0,0 +1,3 @@
+#include "ConfigCommon.xcconfig"
+#include "ConfigCommonRelease.xcconfig"
+#include "ConfigService.xcconfig"
View
@@ -19,6 +19,7 @@
#import "SUPlainInstallerInternals.h"
#import "SUBinaryDeltaCommon.h"
#import "SUUpdater_Private.h"
+#import "SUXPC.h"
@interface SUBasicUpdateDriver () <NSURLDownloadDelegate>; @end
@@ -272,6 +273,10 @@ - (void)installWithToolAndRelaunch:(BOOL)relaunch
[self abortUpdate];
return;
}
+
+ BOOL running10_7 = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
+ BOOL useXPC = running10_7 && [[NSFileManager defaultManager] fileExistsAtPath:
+ [[host bundlePath] stringByAppendingPathComponent:@"Contents/XPCServices/com.andymatuschak.Sparkle.SandboxService.xpc"]];
// Give the host app an opportunity to postpone the install and relaunch.
static BOOL postponedOnce = NO;
@@ -302,7 +307,12 @@ - (void)installWithToolAndRelaunch:(BOOL)relaunch
#endif
// Only the paranoid survive: if there's already a stray copy of relaunch there, we would have problems.
- if( [SUPlainInstaller copyPathWithAuthentication: relaunchPathToCopy overPath: targetPath temporaryName: nil error: &error] )
+ BOOL copiedRelaunchTool = FALSE;
+ if( useXPC )
+ copiedRelaunchTool = [SUXPC copyPathWithAuthentication: relaunchPathToCopy overPath: targetPath temporaryName: nil error: &error];
+ else
+ copiedRelaunchTool = [SUPlainInstaller copyPathWithAuthentication: relaunchPathToCopy overPath: targetPath temporaryName: nil error: &error];
+ if( copiedRelaunchTool )
relaunchPath = [targetPath retain];
else
[self abortUpdateWithError:[NSError errorWithDomain:SUSparkleErrorDomain code:SURelaunchError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:SULocalizedString(@"An error occurred while extracting the archive. Please try again later.", nil), NSLocalizedDescriptionKey, [NSString stringWithFormat:@"Couldn't copy relauncher (%@) to temporary path (%@)! %@", relaunchPathToCopy, targetPath, (error ? [error localizedDescription] : @"")], NSLocalizedFailureReasonErrorKey, nil]]];
@@ -323,7 +333,11 @@ - (void)installWithToolAndRelaunch:(BOOL)relaunch
if ([[updater delegate] respondsToSelector:@selector(pathToRelaunchForUpdater:)])
pathToRelaunch = [[updater delegate] pathToRelaunchForUpdater:updater];
NSString *relaunchToolPath = [relaunchPath stringByAppendingPathComponent: @"/Contents/MacOS/finish_installation"];
- [NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:[NSArray arrayWithObjects:[host bundlePath], pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, relaunch ? @"1" : @"0", nil]];
+ NSArray *arguments = [NSArray arrayWithObjects:[host bundlePath], pathToRelaunch, [NSString stringWithFormat:@"%d", [[NSProcessInfo processInfo] processIdentifier]], tempDir, relaunch ? @"1" : @"0", nil];
+ if( useXPC )
+ [SUXPC launchTaskWithLaunchPath: relaunchToolPath arguments:arguments];
+ else
+ [NSTask launchedTaskWithLaunchPath: relaunchToolPath arguments:arguments];
[NSApp terminate:self];
}
@@ -524,7 +524,10 @@ + (BOOL)copyPathWithAuthentication:(NSString *)src overPath:(NSString *)dst temp
// new home in case it's moved across filesystems: if that
// happens, the move is actually a copy, and it may result
// in the application being quarantined.
- [self performSelectorOnMainThread:@selector(releaseFromQuarantine:) withObject:dst waitUntilDone:YES];
+ if ([NSThread isMultiThreaded])
+ [self performSelectorOnMainThread:@selector(releaseFromQuarantine:) withObject:dst waitUntilDone:YES];
+ else
+ [self releaseFromQuarantine:dst];
return YES;
}
View
16 SUXPC.h
@@ -0,0 +1,16 @@
+//
+// SUXPC.h
+// Sparkle
+//
+// Created by Whitney Young on 3/19/12.
+// Copyright (c) 2012 FadingRed. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface SUXPC : NSObject
+
++ (BOOL)copyPathWithAuthentication:(NSString *)src overPath:(NSString *)dst temporaryName:(NSString *)tmp error:(NSError **)error;
++ (void)launchTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments;
+
+@end
View
72 SUXPC.m
@@ -0,0 +1,72 @@
+//
+// SUXPC.m
+// Sparkle
+//
+// Created by Whitney Young on 3/19/12.
+// Copyright (c) 2012 FadingRed. All rights reserved.
+//
+
+#import <xpc/xpc.h>
+#import "SUXPC.h"
+
+
+@implementation SUXPC
+
++ (BOOL)copyPathWithAuthentication:(NSString *)src overPath:(NSString *)dst temporaryName:(NSString *)tmp error:(NSError **)error {
+ xpc_connection_t connection = xpc_connection_create("com.andymatuschak.Sparkle.SandboxService", NULL);
+ xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
+ xpc_dictionary_apply(event, ^bool(const char *key, xpc_object_t value) {
+ NSLog(@"XPC %s: %s", key, xpc_string_get_string_ptr(value));
+ return true;
+ });
+ });
+ xpc_connection_resume(connection);
+
+ xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_string(message, "id", "copy_path");
+
+ if( src )
+ xpc_dictionary_set_string(message, "source", [src fileSystemRepresentation]);
+ if( dst )
+ xpc_dictionary_set_string(message, "destination", [dst fileSystemRepresentation]);
+ if( tmp )
+ xpc_dictionary_set_string(message, "tmp", [tmp UTF8String]);
+
+ xpc_object_t response = xpc_connection_send_message_with_reply_sync(connection, message);
+ xpc_type_t type = xpc_get_type(response);
+ return type == XPC_TYPE_DICTIONARY;
+}
+
++ (void)launchTaskWithLaunchPath:(NSString *)path arguments:(NSArray *)arguments {
+ xpc_connection_t connection = xpc_connection_create("com.andymatuschak.Sparkle.SandboxService", NULL);
+ xpc_connection_set_event_handler(connection, ^(xpc_object_t event) {
+ xpc_dictionary_apply(event, ^bool(const char *key, xpc_object_t value) {
+ NSLog(@"XPC %s: %s", key, xpc_string_get_string_ptr(value));
+ return true;
+ });
+ });
+ xpc_connection_resume(connection);
+
+ xpc_object_t message = xpc_dictionary_create(NULL, NULL, 0);
+ xpc_dictionary_set_string(message, "id", "launch_task");
+
+ if( path )
+ xpc_dictionary_set_string(message, "path", [path fileSystemRepresentation]);
+
+ xpc_object_t array = xpc_array_create(NULL, 0);
+ for (id argument in arguments) {
+ xpc_array_append_value(array, xpc_string_create([argument UTF8String]));
+ }
+
+ xpc_dictionary_set_value(message, "arguments", array);
+
+ xpc_object_t response = xpc_connection_send_message_with_reply_sync(connection, message);
+ xpc_type_t type = xpc_get_type(response);
+ BOOL success = (type == XPC_TYPE_DICTIONARY);
+
+ if (!success) {
+ NSLog(@"XPC launch error");
+ }
+}
+
+@end
View
@@ -0,0 +1,29 @@
+<?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>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>XPC!</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+ <key>XPCService</key>
+ <dict>
+ <key>ServiceType</key>
+ <string>Application</string>
+ </dict>
+</dict>
+</plist>
Oops, something went wrong.