Commit 3114e51a authored by garykac@chromium.org's avatar garykac@chromium.org

[Chromoting] Update uninstaller to facilitate testing automation.

With this change, if launched from shell as root, the uninstaller will:
* Not show any confirmation UX
* Not prompt for admin elevation

Also in this cl, cleanup some of the shared Mac constants by pushing
more into into constants_mac and fixing up the naming style. This
required minor updates to the prefpane and daemon controller.

BUG=None
TEST=None
Review URL: https://chromiumcodereview.appspot.com/10807061

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148442 0039d316-1c4b-4281-b951-d872f2087c98
parent 0812b714
...@@ -6,6 +6,34 @@ ...@@ -6,6 +6,34 @@
namespace remoting { namespace remoting {
const char kHostHelperTool[] = kHostConfigDir kServiceName ".me2me.sh"; #define SERVICE_NAME "org.chromium.chromoting"
#define APPLICATIONS_DIR "/Applications/"
#define HELPER_TOOLS_DIR "/Library/PrivilegedHelperTools/"
#define LAUNCH_AGENTS_DIR "/Library/LaunchAgents/"
#define PREFERENCE_PANES_DIR "/Library/PreferencePanes/"
const char kServiceName[] = SERVICE_NAME;
const char kUpdateSucceededNotificationName[] =
SERVICE_NAME ".update_succeeded";
const char kUpdateFailedNotificationName[] = SERVICE_NAME ".update_failed";
const char kPrefPaneFileName[] = SERVICE_NAME ".prefPane";
const char kPrefPaneFilePath[] = PREFERENCE_PANES_DIR SERVICE_NAME ".prefPane";
const char kHostConfigFileName[] = SERVICE_NAME ".json";
const char kHostConfigFilePath[] = HELPER_TOOLS_DIR SERVICE_NAME ".json";
const char kHostHelperScriptPath[] = HELPER_TOOLS_DIR SERVICE_NAME ".me2me.sh";
const char kHostBinaryPath[] = HELPER_TOOLS_DIR SERVICE_NAME ".me2me_host.app";
const char kHostEnabledPath[] = HELPER_TOOLS_DIR SERVICE_NAME ".me2me_enabled";
const char kServicePlistPath[] = LAUNCH_AGENTS_DIR SERVICE_NAME ".plist";
const char kBrandedUninstallerPath[] = APPLICATIONS_DIR
"Chrome Remote Desktop Host Uninstaller.app";
const char kUnbrandedUninstallerPath[] = APPLICATIONS_DIR
"Chromoting Host Uninstaller.app";
} // namespace remoting } // namespace remoting
...@@ -8,21 +8,49 @@ ...@@ -8,21 +8,49 @@
namespace remoting { namespace remoting {
// The name of the Remoting Host service that is registered with launchd. // The name of the Remoting Host service that is registered with launchd.
#define kServiceName "org.chromium.chromoting" extern const char kServiceName[];
// Use separate named notifications for success and failure because sandboxed // Use separate named notifications for success and failure because sandboxed
// components can't include a dictionary when sending distributed notifications. // components can't include a dictionary when sending distributed notifications.
// The preferences panel is not yet sandboxed, but err on the side of caution. // The preferences panel is not yet sandboxed, but err on the side of caution.
#define kUpdateSucceededNotificationName kServiceName ".update_succeeded" // These are #defines because they are used with CFSTR macro, which requires
#define kUpdateFailedNotificationName kServiceName ".update_failed" // string literals.
#define UPDATE_SUCCEEDED_NOTIFICATION_NAME \
"org.chromium.chromoting.update_succeeded"
#define UPDATE_FAILED_NOTIFICATION_NAME "org.chromium.chromoting.update_failed"
#define kHostConfigDir "/Library/PrivilegedHelperTools/"
// This helper tool is executed as root to enable/disable/configure the host // Chromoting's preference pane file.
extern const char kPrefPaneFileName[];
extern const char kPrefPaneFilePath[];
// Use a single configuration file, instead of separate "auth" and "host" files.
// This is because the SetConfigAndStart() API only provides a single
// dictionary, and splitting this into two dictionaries would require
// knowledge of which keys belong in which files.
extern const char kHostConfigFileName[];
extern const char kHostConfigFilePath[];
// This helper script is executed as root to enable/disable/configure the host
// service. // service.
// It is also used (as non-root) to provide version information for the // It is also used (as non-root) to provide version information for the
// installed host components. // installed host components.
extern const char kHostHelperTool[]; extern const char kHostHelperScriptPath[];
// Path to the service binary (.app).
extern const char kHostBinaryPath[];
// If this file exists, it means that the host is enabled for sharing.
extern const char kHostEnabledPath[];
// The .plist file for the Chromoting service.
extern const char kServicePlistPath[];
// The branded and unbranded names for the uninstaller.
// This is the only file that changes names based on branding. We define both
// because we want local dev builds to be able to clean up both files.
extern const char kBrandedUninstallerPath[];
extern const char kUnbrandedUninstallerPath[];
} // namespace remoting } // namespace remoting
......
...@@ -4,11 +4,9 @@ ...@@ -4,11 +4,9 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
@interface RemotingUninstallerAppDelegate : NSObject { @interface RemotingUninstaller : NSObject {
} }
- (IBAction)uninstall:(id)sender; - (OSStatus)remotingUninstall;
- (IBAction)cancel:(id)sender;
- (IBAction)handleMenuClose:(NSMenuItem*)sender;
@end @end
...@@ -7,34 +7,10 @@ ...@@ -7,34 +7,10 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#include "base/mac/scoped_authorizationref.h" #include "base/mac/scoped_authorizationref.h"
#include "base/mac/scoped_cftyperef.h"
#include "remoting/host/constants_mac.h" #include "remoting/host/constants_mac.h"
@implementation RemotingUninstallerAppDelegate
NSString* const kLaunchAgentsDir = @"/Library/LaunchAgents"; void logOutput(FILE* pipe) {
NSString* const kPrefPaneDir = @"/Library/PreferencePanes";
NSString* const kHelperToolsDir = @"/Library/PrivilegedHelperTools";
NSString* const kApplicationDir = @"/Applications";
NSString* const kPrefPaneName = @kServiceName ".prefPane";
NSString* const kUninstallerName =
@"Chrome Remote Desktop Host Uninstaller.app";
// Keystone
const char kKeystoneAdmin[] = "/Library/Google/GoogleSoftwareUpdate/"
"GoogleSoftwareUpdate.bundle/Contents/MacOS/"
"ksadmin";
const char kKeystonePID[] = "com.google.chrome_remote_desktop";
- (void)dealloc {
[super dealloc];
}
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
}
- (void)logOutput:(FILE*) pipe {
char readBuffer[128]; char readBuffer[128];
for (;;) { for (;;) {
long bytesRead = read(fileno(pipe), readBuffer, sizeof(readBuffer) - 1); long bytesRead = read(fileno(pipe), readBuffer, sizeof(readBuffer) - 1);
...@@ -45,28 +21,38 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop"; ...@@ -45,28 +21,38 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop";
} }
} }
- (void)messageBox:(const char*)message { NSArray* convertToNSArray(const char** array) {
base::mac::ScopedCFTypeRef<CFStringRef> message_ref( NSMutableArray* ns_array = [[[NSMutableArray alloc] init] autorelease];
CFStringCreateWithCString(NULL, message, (int)strlen(message))); int i = 0;
CFOptionFlags result; const char* element = array[i++];
CFUserNotificationDisplayAlert(0, kCFUserNotificationNoteAlertLevel, while (element != NULL) {
NULL, NULL, NULL, [ns_array addObject:[NSString stringWithUTF8String:element]];
CFSTR("Chrome Remote Desktop Uninstaller"), element = array[i++];
message_ref, NULL, NULL, NULL, &result); }
return ns_array;
} }
-(void)runCommand:(NSString*)cmd @implementation RemotingUninstaller
withArguments:(NSArray*)args {
// Keystone
const char kKeystoneAdmin[] = "/Library/Google/GoogleSoftwareUpdate/"
"GoogleSoftwareUpdate.bundle/Contents/MacOS/"
"ksadmin";
const char kKeystonePID[] = "com.google.chrome_remote_desktop";
- (void)runCommand:(const char*)cmd
withArguments:(const char**)args {
NSTask* task; NSTask* task;
NSPipe* output = [NSPipe pipe]; NSPipe* output = [NSPipe pipe];
NSString* result; NSString* result;
NSLog(@"Executing: %@ %@", cmd, [args componentsJoinedByString:@" "]); NSArray* arg_array = convertToNSArray(args);
NSLog(@"Executing: %s %@", cmd, [arg_array componentsJoinedByString:@" "]);
@try { @try {
task = [[[NSTask alloc] init] autorelease]; task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:cmd]; [task setLaunchPath:[NSString stringWithUTF8String:cmd]];
[task setArguments:args]; [task setArguments:arg_array];
[task setStandardInput:[NSPipe pipe]]; [task setStandardInput:[NSPipe pipe]];
[task setStandardOutput:output]; [task setStandardOutput:output];
[task launch]; [task launch];
...@@ -96,14 +82,7 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop"; ...@@ -96,14 +82,7 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop";
- (void)sudoCommand:(const char*)cmd - (void)sudoCommand:(const char*)cmd
withArguments:(const char**)args withArguments:(const char**)args
usingAuth:(AuthorizationRef)authRef { usingAuth:(AuthorizationRef)authRef {
NSArray* arg_array = convertToNSArray(args);
NSMutableArray* arg_array = [[[NSMutableArray alloc] init] autorelease];
int i = 0;
const char* arg = args[i++];
while (arg != NULL) {
[arg_array addObject:[NSString stringWithUTF8String:arg]];
arg = args[i++];
}
NSLog(@"Executing (as Admin): %s %@", cmd, NSLog(@"Executing (as Admin): %s %@", cmd,
[arg_array componentsJoinedByString:@" "]); [arg_array componentsJoinedByString:@" "]);
FILE* pipe = NULL; FILE* pipe = NULL;
...@@ -118,7 +97,7 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop"; ...@@ -118,7 +97,7 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop";
} else if (status != errAuthorizationSuccess) { } else if (status != errAuthorizationSuccess) {
NSLog(@"Error while executing %s. Status=%lx", cmd, status); NSLog(@"Error while executing %s. Status=%lx", cmd, status);
} else { } else {
[self logOutput:pipe]; logOutput(pipe);
} }
if (pipe != NULL) if (pipe != NULL)
...@@ -131,68 +110,45 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop"; ...@@ -131,68 +110,45 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop";
[self sudoCommand:"/bin/rm" withArguments:args usingAuth:authRef]; [self sudoCommand:"/bin/rm" withArguments:args usingAuth:authRef];
} }
-(void)shutdownService { - (void)shutdownService {
NSString* launchCtl = @"/bin/launchctl"; const char* launchCtl = "/bin/launchctl";
NSArray* argsStop = [NSArray arrayWithObjects:@"stop", const char* argsStop[] = { "stop", remoting::kServiceName, NULL };
@kServiceName, nil];
[self runCommand:launchCtl withArguments:argsStop]; [self runCommand:launchCtl withArguments:argsStop];
NSString* plist = [NSString stringWithFormat:@"%@/%@.plist", if ([[NSFileManager defaultManager] fileExistsAtPath:
kLaunchAgentsDir, @kServiceName]; [NSString stringWithUTF8String:remoting::kServicePlistPath]]) {
if ([[NSFileManager defaultManager] fileExistsAtPath:plist]) { const char* argsUnload[] = { "unload", "-w", "-S", "Aqua",
NSArray* argsUnload = [NSArray arrayWithObjects:@"unload", remoting::kServicePlistPath, NULL };
@"-w", @"-S", @"Aqua", plist, nil];
[self runCommand:launchCtl withArguments:argsUnload]; [self runCommand:launchCtl withArguments:argsUnload];
} }
} }
-(void)keystoneUnregisterUsingAuth:(AuthorizationRef)authRef { - (void)keystoneUnregisterUsingAuth:(AuthorizationRef)authRef {
const char* args[] = { "--delete", "--productid", kKeystonePID, "-S", NULL }; const char* args[] = { "--delete", "--productid", kKeystonePID, "-S", NULL };
[self sudoCommand:kKeystoneAdmin withArguments:args usingAuth:authRef]; [self sudoCommand:kKeystoneAdmin withArguments:args usingAuth:authRef];
} }
-(void)remotingUninstallUsingAuth:(AuthorizationRef)authRef { - (void)remotingUninstallUsingAuth:(AuthorizationRef)authRef {
NSString* host_enabled = [NSString stringWithFormat:@"%@/%@.me2me_enabled", // Remove the enabled file before shutting down the service or else it might
kHelperToolsDir, @kServiceName]; // restart itself.
[self sudoDelete:[host_enabled UTF8String] usingAuth:authRef]; [self sudoDelete:remoting::kHostEnabledPath usingAuth:authRef];
[self shutdownService]; [self shutdownService];
NSString* plist = [NSString stringWithFormat:@"%@/%@.plist", [self sudoDelete:remoting::kServicePlistPath usingAuth:authRef];
kLaunchAgentsDir, @kServiceName]; [self sudoDelete:remoting::kHostBinaryPath usingAuth:authRef];
[self sudoDelete:[plist UTF8String] usingAuth:authRef]; [self sudoDelete:remoting::kHostHelperScriptPath usingAuth:authRef];
[self sudoDelete:remoting::kHostConfigFilePath usingAuth:authRef];
NSString* host_binary = [NSString stringWithFormat:@"%@/%@.me2me_host.app", [self sudoDelete:remoting::kPrefPaneFilePath usingAuth:authRef];
kHelperToolsDir, @kServiceName]; [self sudoDelete:remoting::kBrandedUninstallerPath usingAuth:authRef];
[self sudoDelete:[host_binary UTF8String] usingAuth:authRef]; [self sudoDelete:remoting::kUnbrandedUninstallerPath usingAuth:authRef];
NSString* host_script = [NSString stringWithFormat:@"%@/%@.me2me.sh",
kHelperToolsDir, @kServiceName];
[self sudoDelete:[host_script UTF8String] usingAuth:authRef];
NSString* auth = [NSString stringWithFormat:@"%@/%@.json",
kHelperToolsDir, @kServiceName];
[self sudoDelete:[auth UTF8String] usingAuth:authRef];
NSString* prefpane = [NSString stringWithFormat:@"%@/%@",
kPrefPaneDir, kPrefPaneName];
[self sudoDelete:[prefpane UTF8String] usingAuth:authRef];
NSString* uninstaller = [NSString stringWithFormat:@"%@/%@",
kApplicationDir, kUninstallerName];
[self sudoDelete:[uninstaller UTF8String] usingAuth:authRef];
[self keystoneUnregisterUsingAuth:authRef]; [self keystoneUnregisterUsingAuth:authRef];
} }
- (IBAction)uninstall:(NSButton*)sender { - (OSStatus)remotingUninstall {
base::mac::ScopedAuthorizationRef authRef; base::mac::ScopedAuthorizationRef authRef;
OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
NSLog(@"Chrome Remote Desktop uninstall starting.");
@try {
OSStatus status;
status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
kAuthorizationFlagDefaults, &authRef); kAuthorizationFlagDefaults, &authRef);
if (status != errAuthorizationSuccess) { if (status != errAuthorizationSuccess) {
[NSException raise:@"AuthorizationCreate Failure" [NSException raise:@"AuthorizationCreate Failure"
...@@ -206,44 +162,12 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop"; ...@@ -206,44 +162,12 @@ const char kKeystonePID[] = "com.google.chrome_remote_desktop";
kAuthorizationFlagPreAuthorize | kAuthorizationFlagPreAuthorize |
kAuthorizationFlagExtendRights; kAuthorizationFlagExtendRights;
status = AuthorizationCopyRights(authRef, &rights, NULL, flags, NULL); status = AuthorizationCopyRights(authRef, &rights, NULL, flags, NULL);
if (status == errAuthorizationCanceled) { if (status == errAuthorizationSuccess) {
NSLog(@"Chrome Remote Desktop Host uninstall canceled."); RemotingUninstaller* uninstaller =
const char* message = "Chrome Remote Desktop Host uninstall canceled."; [[[RemotingUninstaller alloc] init] autorelease];
[self messageBox:message]; [uninstaller remotingUninstallUsingAuth:authRef];
} else if (status == errAuthorizationSuccess) {
[self remotingUninstallUsingAuth:authRef];
NSLog(@"Chrome Remote Desktop Host uninstall complete.");
const char* message =
"Chrome Remote Desktop Host was successfully uninstalled.";
[self messageBox:message];
} else {
[NSException raise:@"AuthorizationCopyRights Failure"
format:@"Error during AuthorizationCopyRights status=%ld", status];
}
} }
@catch (NSException* exception) { return status;
NSLog(@"Exception %@ %@", [exception name], [exception reason]);
const char* message =
"Error! Unable to uninstall Chrome Remote Desktop Host.";
[self messageBox:message];
}
[NSApp terminate:self];
}
- (IBAction)cancel:(id)sender {
[NSApp terminate:self];
}
- (IBAction)handleMenuClose:(NSMenuItem*)sender {
[NSApp terminate:self];
} }
@end @end
int main(int argc, char* argv[])
{
return NSApplicationMain(argc, (const char**)argv);
}
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <Cocoa/Cocoa.h>
@interface RemotingUninstallerAppDelegate : NSObject {
}
- (IBAction)uninstall:(id)sender;
- (IBAction)cancel:(id)sender;
- (IBAction)handleMenuClose:(NSMenuItem*)sender;
@end
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/installer/mac/uninstaller/remoting_uninstaller_app.h"
#import <Cocoa/Cocoa.h>
#include "base/mac/scoped_cftyperef.h"
#include "remoting/host/installer/mac/uninstaller/remoting_uninstaller.h"
@implementation RemotingUninstallerAppDelegate
- (void)dealloc {
[super dealloc];
}
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
}
- (void)showSuccess:(bool)success withMessage:(NSString*) message {
NSString* summary = success ? @"Uninstall succeeded" : @"Uninstall failed";
NSAlert* alert = [NSAlert alertWithMessageText:summary
defaultButton:@"OK"
alternateButton:nil
otherButton:nil
informativeTextWithFormat:message];
[alert runModal];
}
- (IBAction)uninstall:(NSButton*)sender {
@try {
NSLog(@"Chrome Remote Desktop uninstall starting.");
RemotingUninstaller* uninstaller =
[[[RemotingUninstaller alloc] init] autorelease];
OSStatus status = [uninstaller remotingUninstall];
NSLog(@"Chrome Remote Desktop Host uninstall complete.");
bool success = false;
NSString* message = NULL;
if (status == errAuthorizationSuccess) {
success = true;
message = @"Chrome Remote Desktop Host successfully uninstalled.";
} else if (status == errAuthorizationCanceled) {
message = @"Chrome Remote Desktop Host uninstall canceled.";
} else if (status == errAuthorizationDenied) {
message = @"Chrome Remote Desktop Host uninstall authorization denied.";
} else {
[NSException raise:@"AuthorizationCopyRights Failure"
format:@"Error during AuthorizationCopyRights status=%ld", status];
}
if (message != NULL) {
NSLog(@"Uninstall %s: %@", success ? "succeeded" : "failed", message);
[self showSuccess:success withMessage:message];
}
}
@catch (NSException* exception) {
NSLog(@"Exception %@ %@", [exception name], [exception reason]);
NSString* message =
@"Error! Unable to uninstall Chrome Remote Desktop Host.";
[self showSuccess:false withMessage:message];
}
[NSApp terminate:self];
}
- (IBAction)cancel:(id)sender {
[NSApp terminate:self];
}
- (IBAction)handleMenuClose:(NSMenuItem*)sender {
[NSApp terminate:self];
}
@end
int main(int argc, char* argv[])
{
// The no-ui option skips the UI confirmation dialogs. This is provided as
// a convenience for our automated testing.
// There will still be an elevation prompt unless the command is run as root.
if (argc == 2 && !strcmp(argv[1], "--no-ui")) {
@autoreleasepool {
NSLog(@"Chrome Remote Desktop uninstall starting.");
NSLog(@"--no-ui : Suppressing UI");
RemotingUninstaller* uninstaller =
[[[RemotingUninstaller alloc] init] autorelease];
OSStatus status = [uninstaller remotingUninstall];
NSLog(@"Chrome Remote Desktop Host uninstall complete.");
NSLog(@"Status = %ld", status);
return status != errAuthorizationSuccess;
}
} else {
return NSApplicationMain(argc, (const char**)argv);
}
}
...@@ -33,8 +33,8 @@ bool GetTemporaryConfigFilePath(std::string* path) { ...@@ -33,8 +33,8 @@ bool GetTemporaryConfigFilePath(std::string* path) {
if (filename == nil) if (filename == nil)
return false; return false;
filename = [filename stringByAppendingString:@"/" kServiceName ".json"]; *path = [[NSString stringWithFormat:@"%@/%s",
*path = [filename UTF8String]; filename, remoting::kHostConfigFileName] UTF8String];
return true; return true;
} }
...@@ -226,6 +226,7 @@ OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization, ...@@ -226,6 +226,7 @@ OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization,
} // namespace base } // namespace base
namespace remoting { namespace remoting {
JsonHostConfig::JsonHostConfig(const std::string& filename) JsonHostConfig::JsonHostConfig(const std::string& filename)
: filename_(filename) { : filename_(filename) {
} }
...@@ -282,7 +283,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -282,7 +283,7 @@ std::string JsonHostConfig::GetSerializedData() const {
[NSDistributedNotificationCenter defaultCenter]; [NSDistributedNotificationCenter defaultCenter];
[center addObserver:self [center addObserver:self
selector:@selector(onNewConfigFile:) selector:@selector(onNewConfigFile:)
name:@kServiceName name:[NSString stringWithUTF8String:remoting::kServiceName]
object:nil]; object:nil];
service_status_timer_ = service_status_timer_ =
...@@ -314,7 +315,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -314,7 +315,7 @@ std::string JsonHostConfig::GetSerializedData() const {
[service_status_timer_ release]; [service_status_timer_ release];
service_status_timer_ = nil; service_status_timer_ = nil;
[self notifyPlugin:kUpdateFailedNotificationName]; [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME];
} }
- (void)applyConfiguration:(id)sender - (void)applyConfiguration:(id)sender
...@@ -358,7 +359,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -358,7 +359,7 @@ std::string JsonHostConfig::GetSerializedData() const {
inputData:""]) { inputData:""]) {
NSLog(@"Failed to run the helper tool"); NSLog(@"Failed to run the helper tool");
[self showError]; [self showError];
[self notifyPlugin: kUpdateFailedNotificationName]; [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME];
return; return;
} }
...@@ -381,7 +382,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -381,7 +382,7 @@ std::string JsonHostConfig::GetSerializedData() const {
[self updateServiceStatus]; [self updateServiceStatus];
if (awaiting_service_stop_ && !is_service_running_) { if (awaiting_service_stop_ && !is_service_running_) {
awaiting_service_stop_ = NO; awaiting_service_stop_ = NO;
[self notifyPlugin:kUpdateSucceededNotificationName]; [self notifyPlugin:UPDATE_SUCCEEDED_NOTIFICATION_NAME];
} }
if (was_running != is_service_running_) if (was_running != is_service_running_)
...@@ -399,7 +400,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -399,7 +400,7 @@ std::string JsonHostConfig::GetSerializedData() const {
} }
- (void)updateServiceStatus { - (void)updateServiceStatus {
pid_t job_pid = base::mac::PIDForJob(kServiceName); pid_t job_pid = base::mac::PIDForJob(remoting::kServiceName);
is_service_running_ = (job_pid > 0); is_service_running_ = (job_pid > 0);
} }
...@@ -525,11 +526,11 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -525,11 +526,11 @@ std::string JsonHostConfig::GetSerializedData() const {
// If the service is running, send a signal to cause it to reload its // If the service is running, send a signal to cause it to reload its
// configuration, otherwise start the service. // configuration, otherwise start the service.
if (is_service_running_) { if (is_service_running_) {
pid_t job_pid = base::mac::PIDForJob(kServiceName); pid_t job_pid = base::mac::PIDForJob(remoting::kServiceName);
if (job_pid > 0) { if (job_pid > 0) {
kill(job_pid, SIGHUP); kill(job_pid, SIGHUP);
} else { } else {
NSLog(@"Failed to obtain PID of service " kServiceName); NSLog(@"Failed to obtain PID of service %s", remoting::kServiceName);
[self showError]; [self showError];
} }
} else { } else {
...@@ -538,7 +539,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -538,7 +539,7 @@ std::string JsonHostConfig::GetSerializedData() const {
// Broadcast a distributed notification to inform the plugin that the // Broadcast a distributed notification to inform the plugin that the
// configuration has been applied. // configuration has been applied.
[self notifyPlugin: kUpdateSucceededNotificationName]; [self notifyPlugin:UPDATE_SUCCEEDED_NOTIFICATION_NAME];
} }
- (BOOL)runHelperAsRootWithCommand:(const char*)command - (BOOL)runHelperAsRootWithCommand:(const char*)command
...@@ -558,7 +559,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -558,7 +559,7 @@ std::string JsonHostConfig::GetSerializedData() const {
pid_t pid; pid_t pid;
OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID( OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID(
authorization, authorization,
remoting::kHostHelperTool, remoting::kHostHelperScriptPath,
kAuthorizationFlagDefaults, kAuthorizationFlagDefaults,
arguments, arguments,
&pipe, &pipe,
...@@ -618,7 +619,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -618,7 +619,7 @@ std::string JsonHostConfig::GetSerializedData() const {
if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) { if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) {
return YES; return YES;
} else { } else {
NSLog(@"%s failed with exit status %d", remoting::kHostHelperTool, NSLog(@"%s failed with exit status %d", remoting::kHostHelperScriptPath,
exit_status); exit_status);
return NO; return NO;
} }
...@@ -626,7 +627,7 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -626,7 +627,7 @@ std::string JsonHostConfig::GetSerializedData() const {
- (BOOL)sendJobControlMessage:(const char*)launch_key { - (BOOL)sendJobControlMessage:(const char*)launch_key {
base::mac::ScopedLaunchData response( base::mac::ScopedLaunchData response(
base::mac::MessageForJob(kServiceName, launch_key)); base::mac::MessageForJob(remoting::kServiceName, launch_key));
if (!response) { if (!response) {
NSLog(@"Failed to send message to launchd"); NSLog(@"Failed to send message to launchd");
[self showError]; [self showError];
...@@ -742,14 +743,14 @@ std::string JsonHostConfig::GetSerializedData() const { ...@@ -742,14 +743,14 @@ std::string JsonHostConfig::GetSerializedData() const {
} }
remove(file.c_str()); remove(file.c_str());
[self notifyPlugin:kUpdateFailedNotificationName]; [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME];
} }
} }
- (void)restartSystemPreferences { - (void)restartSystemPreferences {
NSTask* task = [[NSTask alloc] init]; NSTask* task = [[NSTask alloc] init];
NSString* command = NSString* command =
[NSString stringWithUTF8String:remoting::kHostHelperTool]; [NSString stringWithUTF8String:remoting::kHostHelperScriptPath];
NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil]; NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil];
[task setLaunchPath:command]; [task setLaunchPath:command];
[task setArguments:arguments]; [task setArguments:arguments];
......
...@@ -37,12 +37,6 @@ namespace { ...@@ -37,12 +37,6 @@ namespace {
// Therefore, we define the needed constants here. // Therefore, we define the needed constants here.
const int NSLibraryDirectory = 5; const int NSLibraryDirectory = 5;
// Use a single configuration file, instead of separate "auth" and "host" files.
// This is because the SetConfigAndStart() API only provides a single
// dictionary, and splitting this into two dictionaries would require
// knowledge of which keys belong in which files.
const char kHostConfigFile[] = kHostConfigDir kServiceName ".json";
class DaemonControllerMac : public remoting::DaemonController { class DaemonControllerMac : public remoting::DaemonController {
public: public:
DaemonControllerMac(); DaemonControllerMac();
...@@ -104,12 +98,12 @@ void DaemonControllerMac::DeregisterForPreferencePaneNotifications() { ...@@ -104,12 +98,12 @@ void DaemonControllerMac::DeregisterForPreferencePaneNotifications() {
CFNotificationCenterRemoveObserver( CFNotificationCenterRemoveObserver(
CFNotificationCenterGetDistributedCenter(), CFNotificationCenterGetDistributedCenter(),
this, this,
CFSTR(kUpdateSucceededNotificationName), CFSTR(UPDATE_SUCCEEDED_NOTIFICATION_NAME),
NULL); NULL);
CFNotificationCenterRemoveObserver( CFNotificationCenterRemoveObserver(
CFNotificationCenterGetDistributedCenter(), CFNotificationCenterGetDistributedCenter(),
this, this,
CFSTR(kUpdateFailedNotificationName), CFSTR(UPDATE_FAILED_NOTIFICATION_NAME),
NULL); NULL);
} }
...@@ -180,7 +174,7 @@ void DaemonControllerMac::GetUsageStatsConsent( ...@@ -180,7 +174,7 @@ void DaemonControllerMac::GetUsageStatsConsent(
} }
void DaemonControllerMac::DoGetConfig(const GetConfigCallback& callback) { void DaemonControllerMac::DoGetConfig(const GetConfigCallback& callback) {
FilePath config_path(kHostConfigFile); FilePath config_path(kHostConfigFilePath);
JsonHostConfig host_config(config_path); JsonHostConfig host_config(config_path);
scoped_ptr<base::DictionaryValue> config; scoped_ptr<base::DictionaryValue> config;
...@@ -198,7 +192,7 @@ void DaemonControllerMac::DoGetConfig(const GetConfigCallback& callback) { ...@@ -198,7 +192,7 @@ void DaemonControllerMac::DoGetConfig(const GetConfigCallback& callback) {
void DaemonControllerMac::DoGetVersion(const GetVersionCallback& callback) { void DaemonControllerMac::DoGetVersion(const GetVersionCallback& callback) {
std::string version = ""; std::string version = "";
std::string command_line = remoting::kHostHelperTool; std::string command_line = remoting::kHostHelperScriptPath;
command_line += " --host-version"; command_line += " --host-version";
FILE* script_output = popen(command_line.c_str(), "r"); FILE* script_output = popen(command_line.c_str(), "r");
if (script_output) { if (script_output) {
...@@ -231,7 +225,7 @@ void DaemonControllerMac::DoSetConfigAndStart( ...@@ -231,7 +225,7 @@ void DaemonControllerMac::DoSetConfigAndStart(
void DaemonControllerMac::DoUpdateConfig( void DaemonControllerMac::DoUpdateConfig(
scoped_ptr<base::DictionaryValue> config, scoped_ptr<base::DictionaryValue> config,
const CompletionCallback& done_callback) { const CompletionCallback& done_callback) {
FilePath config_file_path(kHostConfigFile); FilePath config_file_path(kHostConfigFilePath);
JsonHostConfig config_file(config_file_path); JsonHostConfig config_file(config_file_path);
if (!config_file.Read()) { if (!config_file.Read()) {
done_callback.Run(RESULT_FAILED); done_callback.Run(RESULT_FAILED);
...@@ -268,7 +262,7 @@ bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) { ...@@ -268,7 +262,7 @@ bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) {
LOG(ERROR) << "Failed to get filename for saving configuration data."; LOG(ERROR) << "Failed to get filename for saving configuration data.";
return false; return false;
} }
config_path = config_path.Append(kServiceName ".json"); config_path = config_path.Append(kHostConfigFileName);
int written = file_util::WriteFile(config_path, config_data.data(), int written = file_util::WriteFile(config_path, config_data.data(),
config_data.size()); config_data.size());
...@@ -286,8 +280,7 @@ bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) { ...@@ -286,8 +280,7 @@ bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) {
LOG(ERROR) << "Failed to get directory for local preference panes."; LOG(ERROR) << "Failed to get directory for local preference panes.";
return false; return false;
} }
pane_path = pane_path.Append("PreferencePanes") pane_path = pane_path.Append("PreferencePanes").Append(kPrefPaneFileName);
.Append(kServiceName ".prefPane");
FSRef pane_path_ref; FSRef pane_path_ref;
if (!base::mac::FSRefFromPath(pane_path.value(), &pane_path_ref)) { if (!base::mac::FSRefFromPath(pane_path.value(), &pane_path_ref)) {
...@@ -303,7 +296,10 @@ bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) { ...@@ -303,7 +296,10 @@ bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) {
CFNotificationCenterRef center = CFNotificationCenterRef center =
CFNotificationCenterGetDistributedCenter(); CFNotificationCenterGetDistributedCenter();
CFNotificationCenterPostNotification(center, CFSTR(kServiceName), NULL, NULL, base::mac::ScopedCFTypeRef<CFStringRef> service_name(
CFStringCreateWithCString(kCFAllocatorDefault, remoting::kServiceName,
kCFStringEncodingUTF8));
CFNotificationCenterPostNotification(center, service_name, NULL, NULL,
TRUE); TRUE);
return true; return true;
} }
...@@ -328,24 +324,24 @@ void DaemonControllerMac::RegisterForPreferencePaneNotifications( ...@@ -328,24 +324,24 @@ void DaemonControllerMac::RegisterForPreferencePaneNotifications(
CFNotificationCenterGetDistributedCenter(), CFNotificationCenterGetDistributedCenter(),
this, this,
&DaemonControllerMac::PreferencePaneCallback, &DaemonControllerMac::PreferencePaneCallback,
CFSTR(kUpdateSucceededNotificationName), CFSTR(UPDATE_SUCCEEDED_NOTIFICATION_NAME),
NULL, NULL,
CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver( CFNotificationCenterAddObserver(
CFNotificationCenterGetDistributedCenter(), CFNotificationCenterGetDistributedCenter(),
this, this,
&DaemonControllerMac::PreferencePaneCallback, &DaemonControllerMac::PreferencePaneCallback,
CFSTR(kUpdateFailedNotificationName), CFSTR(UPDATE_FAILED_NOTIFICATION_NAME),
NULL, NULL,
CFNotificationSuspensionBehaviorDeliverImmediately); CFNotificationSuspensionBehaviorDeliverImmediately);
} }
void DaemonControllerMac::PreferencePaneCallbackDelegate(CFStringRef name) { void DaemonControllerMac::PreferencePaneCallbackDelegate(CFStringRef name) {
AsyncResult result = RESULT_FAILED; AsyncResult result = RESULT_FAILED;
if (CFStringCompare(name, CFSTR(kUpdateSucceededNotificationName), 0) == if (CFStringCompare(name, CFSTR(UPDATE_SUCCEEDED_NOTIFICATION_NAME), 0) ==
kCFCompareEqualTo) { kCFCompareEqualTo) {
result = RESULT_OK; result = RESULT_OK;
} else if (CFStringCompare(name, CFSTR(kUpdateFailedNotificationName), 0) == } else if (CFStringCompare(name, CFSTR(UPDATE_FAILED_NOTIFICATION_NAME), 0) ==
kCFCompareEqualTo) { kCFCompareEqualTo) {
result = RESULT_FAILED; result = RESULT_FAILED;
} else { } else {
......
...@@ -272,8 +272,12 @@ ...@@ -272,8 +272,12 @@
'<(DEPTH)/base/base.gyp:base', '<(DEPTH)/base/base.gyp:base',
], ],
'sources': [ 'sources': [
'host/constants_mac.cc',
'host/constants_mac.h',
'host/installer/mac/uninstaller/remoting_uninstaller.h', 'host/installer/mac/uninstaller/remoting_uninstaller.h',
'host/installer/mac/uninstaller/remoting_uninstaller.mm', 'host/installer/mac/uninstaller/remoting_uninstaller.mm',
'host/installer/mac/uninstaller/remoting_uninstaller_app.h',
'host/installer/mac/uninstaller/remoting_uninstaller_app.mm',
], ],
'xcode_settings': { 'xcode_settings': {
'INFOPLIST_FILE': 'host/installer/mac/uninstaller/remoting_uninstaller-Info.plist', 'INFOPLIST_FILE': 'host/installer/mac/uninstaller/remoting_uninstaller-Info.plist',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment