diff options
author | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-18 05:03:16 +0000 |
---|---|---|
committer | lambroslambrou@chromium.org <lambroslambrou@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-18 05:03:16 +0000 |
commit | 3efb1b624c74fbdc04a81c4dd186606a097fbfe5 (patch) | |
tree | a043085ef675dc87e31ccbae5c8361c713703f6f /remoting/host/mac | |
parent | c626c735a5aa0501f2f83f6f1f984465c0202e9c (diff) | |
download | chromium_src-3efb1b624c74fbdc04a81c4dd186606a097fbfe5.zip chromium_src-3efb1b624c74fbdc04a81c4dd186606a097fbfe5.tar.gz chromium_src-3efb1b624c74fbdc04a81c4dd186606a097fbfe5.tar.bz2 |
Move remoting pref-pane files to mac/ folder.
Review URL: https://chromiumcodereview.appspot.com/11184031
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162652 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/mac')
-rw-r--r-- | remoting/host/mac/me2me_preference_pane-Info.plist | 36 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane.h | 146 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane.mm | 755 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane.xib | 364 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane_confirm_pin.h | 26 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane_confirm_pin.mm | 46 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane_confirm_pin.xib | 472 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane_disable.h | 20 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane_disable.mm | 30 | ||||
-rw-r--r-- | remoting/host/mac/me2me_preference_pane_disable.xib | 242 |
10 files changed, 2137 insertions, 0 deletions
diff --git a/remoting/host/mac/me2me_preference_pane-Info.plist b/remoting/host/mac/me2me_preference_pane-Info.plist new file mode 100644 index 0000000..1fab228 --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane-Info.plist @@ -0,0 +1,36 @@ +<?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>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>BUNDLE_ID</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>BUNDLE_NAME</string> + <key>CFBundlePackageType</key> + <string>BNDL</string> + <key>CFBundleShortVersionString</key> + <string>VERSION_SHORT</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>VERSION_FULL</string> + <key>NSHumanReadableCopyright</key> + <string>COPYRIGHT_INFO</string> + <key>NSMainNibFile</key> + <string>me2me_preference_pane</string> + <key>NSPrefPaneIconFile</key> + <string>chromoting128.png</string> + <key>NSPrefPaneIconLabel</key> + <string>PREF_PANE_ICON_LABEL</string> + <key>NSPrincipalClass</key> + <string>Me2MePreferencePane</string> +</dict> +</plist> diff --git a/remoting/host/mac/me2me_preference_pane.h b/remoting/host/mac/me2me_preference_pane.h new file mode 100644 index 0000000..d3cfb06 --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane.h @@ -0,0 +1,146 @@ +// 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> +#import <PreferencePanes/PreferencePanes.h> +#import <SecurityInterface/SFAuthorizationView.h> + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "third_party/jsoncpp/source/include/json/value.h" + +namespace remoting { + +// This is an implementation of JsonHostConfig which does not use code from +// the "base" target, so it can be built for 64-bit on Mac OS X. + +// TODO(lambroslambrou): Once the "base" target has 64-bit support, remove this +// implementation and use the one in remoting/host/json_host_config.h - see +// http://crbug.com/128122. +class JsonHostConfig { + public: + JsonHostConfig(const std::string& filename); + ~JsonHostConfig(); + + bool Read(); + bool GetString(const std::string& path, std::string* out_value) const; + std::string GetSerializedData() const; + + private: + Json::Value config_; + std::string filename_; + + DISALLOW_COPY_AND_ASSIGN(JsonHostConfig); +}; + +} + +@class Me2MePreferencePaneConfirmPin; +@class Me2MePreferencePaneDisable; + +@interface Me2MePreferencePane : NSPreferencePane { + Me2MePreferencePaneConfirmPin* confirm_pin_view_; + Me2MePreferencePaneDisable* disable_view_; + + IBOutlet NSTextField* status_message_; + IBOutlet NSBox* box_; + IBOutlet SFAuthorizationView* authorization_view_; + + // Holds the new proposed configuration if a temporary config file is + // present. + scoped_ptr<remoting::JsonHostConfig> config_; + + NSTimer* service_status_timer_; + + // These flags determine the UI state. These are computed in the + // update...Status methods. + BOOL is_service_running_; + BOOL is_pane_unlocked_; + + // True if a new proposed config file has been loaded into memory. + BOOL have_new_config_; + + // True if launchd has been instructed to stop the service and we are waiting + // for the operation to complete. + BOOL awaiting_service_stop_; + + // True if a version-mismatch has been detected. If true, this causes all + // controls to be greyed out, and also prevents any config file from being + // deleted, pending a restart of the preference pane. + BOOL restart_pending_or_canceled_; +} + +- (void)mainViewDidLoad; +- (void)willSelect; +- (void)didSelect; +- (void)willUnselect; +- (void)onDisable:(id)sender; +- (void)applyConfiguration:(id)sender + pin:(NSString*)pin; +- (void)onNewConfigFile:(NSNotification*)notification; +- (void)refreshServiceStatus:(NSTimer*)timer; +- (void)authorizationViewDidAuthorize:(SFAuthorizationView*)view; +- (void)authorizationViewDidDeauthorize:(SFAuthorizationView*)view; +- (void)updateServiceStatus; +- (void)updateAuthorizationStatus; + +// Read any new config file if present. If a config file is successfully read, +// this deletes the file and keeps the config data loaded in memory. If this +// method is called a second time (when the file has been deleted), the current +// config is remembered, so this method acts as a latch: it can change +// |have_new_config_| from NO to YES, but never from YES to NO. +// +// This scheme means that this method can delete the file immediately (to avoid +// leaving a stale file around in case of a crash), but this method can safely +// be called multiple times without forgetting the loaded config. To explicitly +// forget the current config, set |have_new_config_| to NO. +// +// This method should not be called if |restart_pending_or_canceled_| is YES, +// since this would delete any config file. +- (void)readNewConfig; + +// Update all UI controls according to any stored flags and loaded config. +// This should be called after any sequence of operations that might change the +// UI state. +- (void)updateUI; + +// Alert the user to a generic error condition. +- (void)showError; + +// Alert the user that the typed PIN is incorrect. +- (void)showIncorrectPinMessage; + +// Save the new config to the system, and either start the service or inform +// the currently-running service of the new config. +- (void)applyNewServiceConfig; + +- (BOOL)runHelperAsRootWithCommand:(const char*)command + inputData:(const std::string&)input_data; +- (BOOL)sendJobControlMessage:(const char*)launch_key; + +// Compare the version of the running pref-pane against the installed version. +// If the versions are mismatched and the pref-pane is visible, disable the +// pane to prevent interaction, and prompt the user to restart System +// Preferences. +// +// This should be called on notification of a new config, and also in +// |didSelect| when the pane becomes visible. The pane needs to be visible so +// that the alert appears as a sheet over the pane (instead of a detached +// window), which gives the user an appropriate context for the alert. +// +// In the case of a version-mismatch, the new config file should be kept until +// System Preferences is restarted, or thrown away when the user cancels the +// alert. This method sets the |restart_pending_or_canceled_| flag on +// detecting version-mismatch. +- (void)checkInstalledVersion; + +- (void)mismatchAlertDidEnd:(NSAlert*)alert + returnCode:(NSInteger)returnCode + contextInfo:(void*)contextInfo; + +// Called when the user chooses OK when prompted to restart System Preferences. +- (void)restartSystemPreferences; + +@end diff --git a/remoting/host/mac/me2me_preference_pane.mm b/remoting/host/mac/me2me_preference_pane.mm new file mode 100644 index 0000000..ad4ac3c --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane.mm @@ -0,0 +1,755 @@ +// 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 "remoting/host/mac/me2me_preference_pane.h" + +#import <Cocoa/Cocoa.h> +#include <CommonCrypto/CommonHMAC.h> +#include <errno.h> +#include <launch.h> +#import <PreferencePanes/PreferencePanes.h> +#import <SecurityInterface/SFAuthorizationView.h> +#include <stdlib.h> +#include <unistd.h> + +#include <fstream> + +#include "base/eintr_wrapper.h" +#include "base/mac/scoped_launch_data.h" +#include "base/memory/scoped_ptr.h" +#include "remoting/host/constants_mac.h" +#include "remoting/host/host_config.h" +#import "remoting/host/mac/me2me_preference_pane_confirm_pin.h" +#import "remoting/host/mac/me2me_preference_pane_disable.h" +#include "third_party/jsoncpp/source/include/json/reader.h" +#include "third_party/jsoncpp/source/include/json/writer.h" +#include "third_party/modp_b64/modp_b64.h" + +namespace { + +bool GetTemporaryConfigFilePath(std::string* path) { + NSString* filename = NSTemporaryDirectory(); + if (filename == nil) + return false; + + *path = [[NSString stringWithFormat:@"%@/%s", + filename, remoting::kHostConfigFileName] UTF8String]; + return true; +} + +bool IsConfigValid(const remoting::JsonHostConfig* config) { + std::string value; + return (config->GetString(remoting::kHostIdConfigPath, &value) && + config->GetString(remoting::kHostSecretHashConfigPath, &value) && + config->GetString(remoting::kXmppLoginConfigPath, &value)); +} + +bool IsPinValid(const std::string& pin, const std::string& host_id, + const std::string& host_secret_hash) { + // TODO(lambroslambrou): Once the "base" target supports building for 64-bit + // on Mac OS X, remove this code and replace it with |VerifyHostPinHash()| + // from host/pin_hash.h. + size_t separator = host_secret_hash.find(':'); + if (separator == std::string::npos) + return false; + + std::string method = host_secret_hash.substr(0, separator); + if (method != "hmac") { + NSLog(@"Authentication method '%s' not supported", method.c_str()); + return false; + } + + std::string hash_base64 = host_secret_hash.substr(separator + 1); + + // Convert |hash_base64| to |hash|, based on code from base/base64.cc. + int hash_base64_size = static_cast<int>(hash_base64.size()); + std::string hash; + hash.resize(modp_b64_decode_len(hash_base64_size)); + + // modp_b64_decode_len() returns at least 1, so hash[0] is safe here. + int hash_size = modp_b64_decode(&(hash[0]), hash_base64.data(), + hash_base64_size); + if (hash_size < 0) { + NSLog(@"Failed to parse host_secret_hash"); + return false; + } + hash.resize(hash_size); + + std::string computed_hash; + computed_hash.resize(CC_SHA256_DIGEST_LENGTH); + + CCHmac(kCCHmacAlgSHA256, + host_id.data(), host_id.size(), + pin.data(), pin.size(), + &(computed_hash[0])); + + // Normally, a constant-time comparison function would be used, but it is + // unnecessary here as the "secret" is already readable by the user + // supplying input to this routine. + return computed_hash == hash; +} + +} // namespace + +// These methods are copied from base/mac, but with the logging changed to use +// NSLog(). +// +// TODO(lambroslambrou): Once the "base" target supports building for 64-bit +// on Mac OS X, remove these implementations and use the ones in base/mac. +namespace base { +namespace mac { + +// MessageForJob sends a single message to launchd with a simple dictionary +// mapping |operation| to |job_label|, and returns the result of calling +// launch_msg to send that message. On failure, returns NULL. The caller +// assumes ownership of the returned launch_data_t object. +launch_data_t MessageForJob(const std::string& job_label, + const char* operation) { + // launch_data_alloc returns something that needs to be freed. + ScopedLaunchData message(launch_data_alloc(LAUNCH_DATA_DICTIONARY)); + if (!message) { + NSLog(@"launch_data_alloc"); + return NULL; + } + + // launch_data_new_string returns something that needs to be freed, but + // the dictionary will assume ownership when launch_data_dict_insert is + // called, so put it in a scoper and .release() it when given to the + // dictionary. + ScopedLaunchData job_label_launchd(launch_data_new_string(job_label.c_str())); + if (!job_label_launchd) { + NSLog(@"launch_data_new_string"); + return NULL; + } + + if (!launch_data_dict_insert(message, + job_label_launchd.release(), + operation)) { + return NULL; + } + + return launch_msg(message); +} + +pid_t PIDForJob(const std::string& job_label) { + ScopedLaunchData response(MessageForJob(job_label, LAUNCH_KEY_GETJOB)); + if (!response) { + return -1; + } + + launch_data_type_t response_type = launch_data_get_type(response); + if (response_type != LAUNCH_DATA_DICTIONARY) { + if (response_type == LAUNCH_DATA_ERRNO) { + NSLog(@"PIDForJob: error %d", launch_data_get_errno(response)); + } else { + NSLog(@"PIDForJob: expected dictionary, got %d", response_type); + } + return -1; + } + + launch_data_t pid_data = launch_data_dict_lookup(response, + LAUNCH_JOBKEY_PID); + if (!pid_data) + return 0; + + if (launch_data_get_type(pid_data) != LAUNCH_DATA_INTEGER) { + NSLog(@"PIDForJob: expected integer"); + return -1; + } + + return launch_data_get_integer(pid_data); +} + +OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization, + const char* tool_path, + AuthorizationFlags options, + const char** arguments, + FILE** pipe, + pid_t* pid) { + // pipe may be NULL, but this function needs one. In that case, use a local + // pipe. + FILE* local_pipe; + FILE** pipe_pointer; + if (pipe) { + pipe_pointer = pipe; + } else { + pipe_pointer = &local_pipe; + } + + // AuthorizationExecuteWithPrivileges wants |char* const*| for |arguments|, + // but it doesn't actually modify the arguments, and that type is kind of + // silly and callers probably aren't dealing with that. Put the cast here + // to make things a little easier on callers. + OSStatus status = AuthorizationExecuteWithPrivileges(authorization, + tool_path, + options, + (char* const*)arguments, + pipe_pointer); + if (status != errAuthorizationSuccess) { + return status; + } + + long line_pid = -1; + size_t line_length = 0; + char* line_c = fgetln(*pipe_pointer, &line_length); + if (line_c) { + if (line_length > 0 && line_c[line_length - 1] == '\n') { + // line_c + line_length is the start of the next line if there is one. + // Back up one character. + --line_length; + } + std::string line(line_c, line_length); + + // The version in base/mac used base::StringToInt() here. + line_pid = strtol(line.c_str(), NULL, 10); + if (line_pid == 0) { + NSLog(@"ExecuteWithPrivilegesAndGetPid: funny line: %s", line.c_str()); + line_pid = -1; + } + } else { + NSLog(@"ExecuteWithPrivilegesAndGetPid: no line"); + } + + if (!pipe) { + fclose(*pipe_pointer); + } + + if (pid) { + *pid = line_pid; + } + + return status; +} + +} // namespace mac +} // namespace base + +namespace remoting { + +JsonHostConfig::JsonHostConfig(const std::string& filename) + : filename_(filename) { +} + +JsonHostConfig::~JsonHostConfig() { +} + +bool JsonHostConfig::Read() { + std::ifstream file(filename_.c_str()); + Json::Reader reader; + return reader.parse(file, config_, false /* ignore comments */); +} + +bool JsonHostConfig::GetString(const std::string& path, + std::string* out_value) const { + if (!config_.isObject()) + return false; + + if (!config_.isMember(path)) + return false; + + Json::Value value = config_[path]; + if (!value.isString()) + return false; + + *out_value = value.asString(); + return true; +} + +std::string JsonHostConfig::GetSerializedData() const { + Json::FastWriter writer; + return writer.write(config_); +} + +} // namespace remoting + +@implementation Me2MePreferencePane + +- (void)mainViewDidLoad { + [authorization_view_ setDelegate:self]; + [authorization_view_ setString:kAuthorizationRightExecute]; + [authorization_view_ setAutoupdate:YES + interval:60]; + confirm_pin_view_ = [[Me2MePreferencePaneConfirmPin alloc] init]; + [confirm_pin_view_ setDelegate:self]; + disable_view_ = [[Me2MePreferencePaneDisable alloc] init]; + [disable_view_ setDelegate:self]; +} + +- (void)willSelect { + have_new_config_ = NO; + awaiting_service_stop_ = NO; + + NSDistributedNotificationCenter* center = + [NSDistributedNotificationCenter defaultCenter]; + [center addObserver:self + selector:@selector(onNewConfigFile:) + name:[NSString stringWithUTF8String:remoting::kServiceName] + object:nil]; + + service_status_timer_ = + [[NSTimer scheduledTimerWithTimeInterval:2.0 + target:self + selector:@selector(refreshServiceStatus:) + userInfo:nil + repeats:YES] retain]; + [self updateServiceStatus]; + [self updateAuthorizationStatus]; + + [self checkInstalledVersion]; + if (!restart_pending_or_canceled_) + [self readNewConfig]; + + [self updateUI]; +} + +- (void)didSelect { + [self checkInstalledVersion]; +} + +- (void)willUnselect { + NSDistributedNotificationCenter* center = + [NSDistributedNotificationCenter defaultCenter]; + [center removeObserver:self]; + + [service_status_timer_ invalidate]; + [service_status_timer_ release]; + service_status_timer_ = nil; + + [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME]; +} + +- (void)applyConfiguration:(id)sender + pin:(NSString*)pin { + if (!have_new_config_) { + // It shouldn't be possible to hit the button if there is no config to + // apply, but check anyway just in case it happens somehow. + return; + } + + // Ensure the authorization token is up-to-date before using it. + [self updateAuthorizationStatus]; + [self updateUI]; + + std::string pin_utf8 = [pin UTF8String]; + std::string host_id, host_secret_hash; + bool result = (config_->GetString(remoting::kHostIdConfigPath, &host_id) && + config_->GetString(remoting::kHostSecretHashConfigPath, + &host_secret_hash)); + if (!result) { + [self showError]; + return; + } + if (!IsPinValid(pin_utf8, host_id, host_secret_hash)) { + [self showIncorrectPinMessage]; + return; + } + + [self applyNewServiceConfig]; + [self updateUI]; +} + +- (void)onDisable:(id)sender { + // Ensure the authorization token is up-to-date before using it. + [self updateAuthorizationStatus]; + [self updateUI]; + if (!is_pane_unlocked_) + return; + + if (![self runHelperAsRootWithCommand:"--disable" + inputData:""]) { + NSLog(@"Failed to run the helper tool"); + [self showError]; + [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME]; + return; + } + + // Stop the launchd job. This cannot easily be done by the helper tool, + // since the launchd job runs in the current user's context. + [self sendJobControlMessage:LAUNCH_KEY_STOPJOB]; + awaiting_service_stop_ = YES; +} + +- (void)onNewConfigFile:(NSNotification*)notification { + [self checkInstalledVersion]; + if (!restart_pending_or_canceled_) + [self readNewConfig]; + + [self updateUI]; +} + +- (void)refreshServiceStatus:(NSTimer*)timer { + BOOL was_running = is_service_running_; + [self updateServiceStatus]; + if (awaiting_service_stop_ && !is_service_running_) { + awaiting_service_stop_ = NO; + [self notifyPlugin:UPDATE_SUCCEEDED_NOTIFICATION_NAME]; + } + + if (was_running != is_service_running_) + [self updateUI]; +} + +- (void)authorizationViewDidAuthorize:(SFAuthorizationView*)view { + [self updateAuthorizationStatus]; + [self updateUI]; +} + +- (void)authorizationViewDidDeauthorize:(SFAuthorizationView*)view { + [self updateAuthorizationStatus]; + [self updateUI]; +} + +- (void)updateServiceStatus { + pid_t job_pid = base::mac::PIDForJob(remoting::kServiceName); + is_service_running_ = (job_pid > 0); +} + +- (void)updateAuthorizationStatus { + is_pane_unlocked_ = [authorization_view_ updateStatus:authorization_view_]; +} + +- (void)readNewConfig { + std::string file; + if (!GetTemporaryConfigFilePath(&file)) { + NSLog(@"Failed to get path of configuration data."); + [self showError]; + return; + } + if (access(file.c_str(), F_OK) != 0) + return; + + scoped_ptr<remoting::JsonHostConfig> new_config_( + new remoting::JsonHostConfig(file)); + if (!new_config_->Read()) { + // Report the error, because the file exists but couldn't be read. The + // case of non-existence is normal and expected. + NSLog(@"Error reading configuration data from %s", file.c_str()); + [self showError]; + return; + } + remove(file.c_str()); + if (!IsConfigValid(new_config_.get())) { + NSLog(@"Invalid configuration data read."); + [self showError]; + return; + } + + config_.swap(new_config_); + have_new_config_ = YES; + + [confirm_pin_view_ resetPin]; +} + +- (void)updateUI { + if (have_new_config_) { + [box_ setContentView:[confirm_pin_view_ view]]; + } else { + [box_ setContentView:[disable_view_ view]]; + } + + // TODO(lambroslambrou): Show "enabled" and "disabled" in bold font. + NSString* message; + if (is_service_running_) { + if (have_new_config_) { + message = @"Please confirm your new PIN."; + } else { + message = @"Remote connections to this computer are enabled."; + } + } else { + if (have_new_config_) { + message = @"Remote connections to this computer are disabled. To enable " + "remote connections you must confirm your PIN."; + } else { + message = @"Remote connections to this computer are disabled."; + } + } + [status_message_ setStringValue:message]; + + std::string email; + if (config_.get()) { + bool result = config_->GetString(remoting::kXmppLoginConfigPath, &email); + + // The config has already been checked by |IsConfigValid|. + if (!result) { + [self showError]; + return; + } + } + [disable_view_ setEnabled:(is_pane_unlocked_ && is_service_running_ && + !restart_pending_or_canceled_)]; + [confirm_pin_view_ setEnabled:(is_pane_unlocked_ && + !restart_pending_or_canceled_)]; + [confirm_pin_view_ setEmail:[NSString stringWithUTF8String:email.c_str()]]; + NSString* applyButtonText = is_service_running_ ? @"Confirm" : @"Enable"; + [confirm_pin_view_ setButtonText:applyButtonText]; + + if (restart_pending_or_canceled_) + [authorization_view_ setEnabled:NO]; +} + +- (void)showError { + NSAlert* alert = [[NSAlert alloc] init]; + [alert setMessageText:@"An unexpected error occurred."]; + [alert setInformativeText:@"Check the system log for more information."]; + [alert setAlertStyle:NSWarningAlertStyle]; + [alert beginSheetModalForWindow:[[self mainView] window] + modalDelegate:nil + didEndSelector:nil + contextInfo:nil]; + [alert release]; +} + +- (void)showIncorrectPinMessage { + NSAlert* alert = [[NSAlert alloc] init]; + [alert setMessageText:@"Incorrect PIN entered."]; + [alert setAlertStyle:NSWarningAlertStyle]; + [alert beginSheetModalForWindow:[[self mainView] window] + modalDelegate:nil + didEndSelector:nil + contextInfo:nil]; + [alert release]; +} + +- (void)applyNewServiceConfig { + [self updateServiceStatus]; + std::string serialized_config = config_->GetSerializedData(); + const char* command = is_service_running_ ? "--save-config" : "--enable"; + if (![self runHelperAsRootWithCommand:command + inputData:serialized_config]) { + NSLog(@"Failed to run the helper tool"); + [self showError]; + return; + } + + have_new_config_ = NO; + + // Ensure the service is started. + if (!is_service_running_) { + [self sendJobControlMessage:LAUNCH_KEY_STARTJOB]; + } + + // Broadcast a distributed notification to inform the plugin that the + // configuration has been applied. + [self notifyPlugin:UPDATE_SUCCEEDED_NOTIFICATION_NAME]; +} + +- (BOOL)runHelperAsRootWithCommand:(const char*)command + inputData:(const std::string&)input_data { + AuthorizationRef authorization = + [[authorization_view_ authorization] authorizationRef]; + if (!authorization) { + NSLog(@"Failed to obtain authorizationRef"); + return NO; + } + + // TODO(lambroslambrou): Replace the deprecated ExecuteWithPrivileges + // call with a launchd-based helper tool, which is more secure. + // http://crbug.com/120903 + const char* arguments[] = { command, NULL }; + FILE* pipe = NULL; + pid_t pid; + OSStatus status = base::mac::ExecuteWithPrivilegesAndGetPID( + authorization, + remoting::kHostHelperScriptPath, + kAuthorizationFlagDefaults, + arguments, + &pipe, + &pid); + if (status != errAuthorizationSuccess) { + NSLog(@"AuthorizationExecuteWithPrivileges: %s (%d)", + GetMacOSStatusErrorString(status), static_cast<int>(status)); + return NO; + } + if (pid == -1) { + NSLog(@"Failed to get child PID"); + if (pipe) + fclose(pipe); + + return NO; + } + if (!pipe) { + NSLog(@"Unexpected NULL pipe"); + return NO; + } + + // Some cleanup is needed (closing the pipe and waiting for the child + // process), so flag any errors before returning. + BOOL error = NO; + + if (!input_data.empty()) { + size_t bytes_written = fwrite(input_data.data(), sizeof(char), + input_data.size(), pipe); + // According to the fwrite manpage, a partial count is returned only if a + // write error has occurred. + if (bytes_written != input_data.size()) { + NSLog(@"Failed to write data to child process"); + error = YES; + } + } + + // In all cases, fclose() should be called with the returned FILE*. In the + // case of sending data to the child, this needs to be done before calling + // waitpid(), since the child reads until EOF on its stdin, so calling + // waitpid() first would result in deadlock. + if (fclose(pipe) != 0) { + NSLog(@"fclose failed with error %d", errno); + error = YES; + } + + int exit_status; + pid_t wait_result = HANDLE_EINTR(waitpid(pid, &exit_status, 0)); + if (wait_result != pid) { + NSLog(@"waitpid failed with error %d", errno); + error = YES; + } + + // No more cleanup needed. + if (error) + return NO; + + if (WIFEXITED(exit_status) && WEXITSTATUS(exit_status) == 0) { + return YES; + } else { + NSLog(@"%s failed with exit status %d", remoting::kHostHelperScriptPath, + exit_status); + return NO; + } +} + +- (BOOL)sendJobControlMessage:(const char*)launch_key { + base::mac::ScopedLaunchData response( + base::mac::MessageForJob(remoting::kServiceName, launch_key)); + if (!response) { + NSLog(@"Failed to send message to launchd"); + [self showError]; + return NO; + } + + // Expect a response of type LAUNCH_DATA_ERRNO. + launch_data_type_t type = launch_data_get_type(response.get()); + if (type != LAUNCH_DATA_ERRNO) { + NSLog(@"launchd returned unexpected type: %d", type); + [self showError]; + return NO; + } + + int error = launch_data_get_errno(response.get()); + if (error) { + NSLog(@"launchd returned error: %d", error); + [self showError]; + return NO; + } + return YES; +} + +- (void)notifyPlugin:(const char*)message { + NSDistributedNotificationCenter* center = + [NSDistributedNotificationCenter defaultCenter]; + NSString* name = [NSString stringWithUTF8String:message]; + [center postNotificationName:name + object:nil + userInfo:nil]; +} + +- (void)checkInstalledVersion { + // There's no point repeating the check if the pane has already been disabled + // from a previous call to this method. The pane only gets disabled when a + // version-mismatch has been detected here, so skip the check, but continue to + // handle the version-mismatch case. + if (!restart_pending_or_canceled_) { + NSBundle* this_bundle = [NSBundle bundleForClass:[self class]]; + NSDictionary* this_plist = [this_bundle infoDictionary]; + NSString* this_version = [this_plist objectForKey:@"CFBundleVersion"]; + + NSString* bundle_path = [this_bundle bundlePath]; + NSString* plist_path = + [bundle_path stringByAppendingString:@"/Contents/Info.plist"]; + NSDictionary* disk_plist = + [NSDictionary dictionaryWithContentsOfFile:plist_path]; + NSString* disk_version = [disk_plist objectForKey:@"CFBundleVersion"]; + + if (disk_version == nil) { + NSLog(@"Failed to get installed version information"); + [self showError]; + return; + } + + if ([this_version isEqualToString:disk_version]) + return; + + restart_pending_or_canceled_ = YES; + [self updateUI]; + } + + NSWindow* window = [[self mainView] window]; + if (window == nil) { + // Defer the alert until |didSelect| is called, which happens just after + // the window is created. + return; + } + + // This alert appears as a sheet over the top of the Chromoting pref-pane, + // underneath the title, so it's OK to refer to "this preference pane" rather + // than repeat the title "Chromoting" here. + NSAlert* alert = [[NSAlert alloc] init]; + [alert setMessageText:@"System update detected"]; + [alert setInformativeText:@"To use this preference pane, System Preferences " + "needs to be restarted"]; + [alert addButtonWithTitle:@"OK"]; + NSButton* cancel_button = [alert addButtonWithTitle:@"Cancel"]; + [cancel_button setKeyEquivalent:@"\e"]; + [alert setAlertStyle:NSWarningAlertStyle]; + [alert beginSheetModalForWindow:window + modalDelegate:self + didEndSelector:@selector( + mismatchAlertDidEnd:returnCode:contextInfo:) + contextInfo:nil]; + [alert release]; +} + +- (void)mismatchAlertDidEnd:(NSAlert*)alert + returnCode:(NSInteger)returnCode + contextInfo:(void*)contextInfo { + if (returnCode == NSAlertFirstButtonReturn) { + // OK was pressed. + + // Dismiss the alert window here, so that the application will respond to + // the NSApp terminate: message. + [[alert window] orderOut:nil]; + [self restartSystemPreferences]; + } else { + // Cancel was pressed. + + // If there is a new config file, delete it and notify the web-app of + // failure to apply the config. Otherwise, the web-app will remain in a + // spinning state until System Preferences eventually gets restarted and + // the user visits this pane again. + std::string file; + if (!GetTemporaryConfigFilePath(&file)) { + // There's no point in alerting the user here. The same error would + // happen when the pane is eventually restarted, so the user would be + // alerted at that time. + NSLog(@"Failed to get path of configuration data."); + return; + } + + remove(file.c_str()); + [self notifyPlugin:UPDATE_FAILED_NOTIFICATION_NAME]; + } +} + +- (void)restartSystemPreferences { + NSTask* task = [[NSTask alloc] init]; + NSString* command = + [NSString stringWithUTF8String:remoting::kHostHelperScriptPath]; + NSArray* arguments = [NSArray arrayWithObjects:@"--relaunch-prefpane", nil]; + [task setLaunchPath:command]; + [task setArguments:arguments]; + [task setStandardInput:[NSPipe pipe]]; + [task launch]; + [task release]; + [NSApp terminate:nil]; +} + +@end diff --git a/remoting/host/mac/me2me_preference_pane.xib b/remoting/host/mac/me2me_preference_pane.xib new file mode 100644 index 0000000..bf6363c --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane.xib @@ -0,0 +1,364 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00"> + <data> + <int key="IBDocument.SystemTarget">1050</int> + <string key="IBDocument.SystemVersion">12C54</string> + <string key="IBDocument.InterfaceBuilderVersion">2549</string> + <string key="IBDocument.AppKitVersion">1187.34</string> + <string key="IBDocument.HIToolboxVersion">625.00</string> + <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="NS.object.0">2549</string> + </object> + <array key="IBDocument.IntegratedClassDependencies"> + <string>NSBox</string> + <string>NSCustomObject</string> + <string>NSCustomView</string> + <string>NSTextField</string> + <string>NSTextFieldCell</string> + <string>NSView</string> + <string>NSWindowTemplate</string> + </array> + <array key="IBDocument.PluginDependencies"> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </array> + <object class="NSMutableDictionary" key="IBDocument.Metadata"> + <string key="NS.key.0">PluginDependencyRecalculationVersion</string> + <integer value="1" key="NS.object.0"/> + </object> + <array class="NSMutableArray" key="IBDocument.RootObjects" id="409411428"> + <object class="NSCustomObject" id="294453543"> + <string key="NSClassName">Me2MePreferencePane</string> + </object> + <object class="NSCustomObject" id="308860122"> + <string key="NSClassName">FirstResponder</string> + </object> + <object class="NSCustomObject" id="278121016"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSWindowTemplate" id="660800786"> + <int key="NSWindowStyleMask">7</int> + <int key="NSWindowBacking">2</int> + <string key="NSWindowRect">{{176, 764}, {667, 243}}</string> + <int key="NSWTFlags">1081606144</int> + <string key="NSWindowTitle"><< do not localize >></string> + <string key="NSWindowClass">NSWindow</string> + <object class="NSMutableString" key="NSViewClass"> + <characters key="NS.bytes">View</characters> + </object> + <nil key="NSUserInterfaceItemIdentifier"/> + <string key="NSWindowContentMinSize">{224.66399999999999, 10}</string> + <object class="NSView" key="NSWindowView" id="1037298196"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">256</int> + <array class="NSMutableArray" key="NSSubviews"> + <object class="NSCustomView" id="737813299"> + <reference key="NSNextResponder" ref="1037298196"/> + <int key="NSvFlags">303</int> + <string key="NSFrame">{{20, 20}, {627, 47}}</string> + <reference key="NSSuperview" ref="1037298196"/> + <reference key="NSWindow"/> + <string key="NSClassName">SFAuthorizationView</string> + </object> + <object class="NSBox" id="1043481212"> + <reference key="NSNextResponder" ref="1037298196"/> + <int key="NSvFlags">12</int> + <array class="NSMutableArray" key="NSSubviews"> + <object class="NSView" id="659966804"> + <reference key="NSNextResponder" ref="1043481212"/> + <int key="NSvFlags">274</int> + <string key="NSFrameSize">{633, 106}</string> + <reference key="NSSuperview" ref="1043481212"/> + <reference key="NSWindow"/> + </object> + </array> + <string key="NSFrame">{{17, 71}, {633, 106}}</string> + <reference key="NSSuperview" ref="1037298196"/> + <reference key="NSWindow"/> + <string key="NSOffsets">{0, 0}</string> + <object class="NSTextFieldCell" key="NSTitleCell"> + <int key="NSCellFlags">67108864</int> + <int key="NSCellFlags2">0</int> + <string key="NSContents">Box</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">11</double> + <int key="NSfFlags">3100</int> + </object> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textBackgroundColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MCAwLjgwMDAwMDAxMTkAA</bytes> + </object> + </object> + <reference key="NSContentView" ref="659966804"/> + <int key="NSBorderType">0</int> + <int key="NSBoxType">0</int> + <int key="NSTitlePosition">0</int> + <bool key="NSTransparent">NO</bool> + </object> + <object class="NSTextField" id="129220543"> + <reference key="NSNextResponder" ref="1037298196"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{17, 183}, {633, 40}}</string> + <reference key="NSSuperview" ref="1037298196"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="62099194"> + <int key="NSCellFlags">67108864</int> + <int key="NSCellFlags2">4456448</int> + <string key="NSContents">Status</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">13</double> + <int key="NSfFlags">16</int> + </object> + <reference key="NSControlView" ref="129220543"/> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> + </object> + </object> + <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + </object> + </array> + <string key="NSFrameSize">{667, 243}</string> + <reference key="NSSuperview"/> + <reference key="NSWindow"/> + </object> + <string key="NSScreenRect">{{0, 0}, {2560, 1578}}</string> + <string key="NSMinSize">{224.66399999999999, 32}</string> + <string key="NSMaxSize">{10000000000000, 10000000000000}</string> + <bool key="NSWindowIsRestorable">YES</bool> + </object> + </array> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <array class="NSMutableArray" key="connectionRecords"> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">_window</string> + <reference key="source" ref="294453543"/> + <reference key="destination" ref="660800786"/> + </object> + <int key="connectionID">26</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">authorization_view_</string> + <reference key="source" ref="294453543"/> + <reference key="destination" ref="737813299"/> + </object> + <int key="connectionID">108</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">box_</string> + <reference key="source" ref="294453543"/> + <reference key="destination" ref="1043481212"/> + </object> + <int key="connectionID">126</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">status_message_</string> + <reference key="source" ref="294453543"/> + <reference key="destination" ref="129220543"/> + </object> + <int key="connectionID">127</int> + </object> + </array> + <object class="IBMutableOrderedSet" key="objectRecords"> + <array key="orderedObjects"> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <array key="object" id="0"/> + <reference key="children" ref="409411428"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-2</int> + <reference key="object" ref="294453543"/> + <reference key="parent" ref="0"/> + <string key="objectName">File's Owner</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-1</int> + <reference key="object" ref="308860122"/> + <reference key="parent" ref="0"/> + <string key="objectName">First Responder</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">12</int> + <reference key="object" ref="660800786"/> + <array class="NSMutableArray" key="children"> + <reference ref="1037298196"/> + </array> + <reference key="parent" ref="0"/> + <string key="objectName">PrefPane</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">6</int> + <reference key="object" ref="1037298196"/> + <array class="NSMutableArray" key="children"> + <reference ref="1043481212"/> + <reference ref="737813299"/> + <reference ref="129220543"/> + </array> + <reference key="parent" ref="660800786"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-3</int> + <reference key="object" ref="278121016"/> + <reference key="parent" ref="0"/> + <string key="objectName">Application</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">105</int> + <reference key="object" ref="737813299"/> + <reference key="parent" ref="1037298196"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">123</int> + <reference key="object" ref="1043481212"/> + <reference key="parent" ref="1037298196"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">124</int> + <reference key="object" ref="129220543"/> + <array class="NSMutableArray" key="children"> + <reference ref="62099194"/> + </array> + <reference key="parent" ref="1037298196"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">125</int> + <reference key="object" ref="62099194"/> + <reference key="parent" ref="129220543"/> + </object> + </array> + </object> + <dictionary class="NSMutableDictionary" key="flattenedProperties"> + <string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="105.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="12.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="12.IBWindowTemplateEditedContentRect">{{1424, 1107}, {667, 243}}</string> + <string key="123.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="124.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="125.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="6.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string> + </dictionary> + <dictionary class="NSMutableDictionary" key="unlocalizedProperties"/> + <nil key="activeLocalization"/> + <dictionary class="NSMutableDictionary" key="localizations"/> + <nil key="sourceID"/> + <int key="maxID">127</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <array class="NSMutableArray" key="referencedPartialClassDescriptions"> + <object class="IBPartialClassDescription"> + <string key="className">Me2MePreferencePane</string> + <string key="superclassName">NSPreferencePane</string> + <dictionary class="NSMutableDictionary" key="outlets"> + <string key="authorization_view_">SFAuthorizationView</string> + <string key="box_">NSBox</string> + <string key="status_message_">NSTextField</string> + </dictionary> + <dictionary class="NSMutableDictionary" key="toOneOutletInfosByName"> + <object class="IBToOneOutletInfo" key="authorization_view_"> + <string key="name">authorization_view_</string> + <string key="candidateClassName">SFAuthorizationView</string> + </object> + <object class="IBToOneOutletInfo" key="box_"> + <string key="name">box_</string> + <string key="candidateClassName">NSBox</string> + </object> + <object class="IBToOneOutletInfo" key="status_message_"> + <string key="name">status_message_</string> + <string key="candidateClassName">NSTextField</string> + </object> + </dictionary> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/Me2MePreferencePane.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">NSPreferencePane</string> + <string key="superclassName">NSObject</string> + <dictionary class="NSMutableDictionary" key="outlets"> + <string key="_firstKeyView">NSView</string> + <string key="_initialKeyView">NSView</string> + <string key="_lastKeyView">NSView</string> + <string key="_window">NSWindow</string> + </dictionary> + <dictionary class="NSMutableDictionary" key="toOneOutletInfosByName"> + <object class="IBToOneOutletInfo" key="_firstKeyView"> + <string key="name">_firstKeyView</string> + <string key="candidateClassName">NSView</string> + </object> + <object class="IBToOneOutletInfo" key="_initialKeyView"> + <string key="name">_initialKeyView</string> + <string key="candidateClassName">NSView</string> + </object> + <object class="IBToOneOutletInfo" key="_lastKeyView"> + <string key="name">_lastKeyView</string> + <string key="candidateClassName">NSView</string> + </object> + <object class="IBToOneOutletInfo" key="_window"> + <string key="name">_window</string> + <string key="candidateClassName">NSWindow</string> + </object> + </dictionary> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/NSPreferencePane.h</string> + </object> + </object> + <object class="IBPartialClassDescription"> + <string key="className">SFAuthorizationView</string> + <string key="superclassName">NSView</string> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/SFAuthorizationView.h</string> + </object> + </object> + </array> + </object> + <int key="IBDocument.localizationMode">0</int> + <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencies"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> + <real value="1050" key="NS.object.0"/> + </object> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> + <real value="1070" key="NS.object.0"/> + </object> + <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + </data> +</archive> diff --git a/remoting/host/mac/me2me_preference_pane_confirm_pin.h b/remoting/host/mac/me2me_preference_pane_confirm_pin.h new file mode 100644 index 0000000..f16ada3 --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane_confirm_pin.h @@ -0,0 +1,26 @@ +// 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> + +@protocol Me2MePreferencePaneConfirmPinHandler <NSObject> +- (void)applyConfiguration:(id)sender pin:(NSString*)pin; +@end + +@interface Me2MePreferencePaneConfirmPin : NSViewController { + IBOutlet NSTextField* email_; + IBOutlet NSTextField* pin_; + IBOutlet NSButton* apply_button_; + id delegate_; +} + +@property (retain) id delegate; + +- (void)setEmail:(NSString*)email; +- (void)setButtonText:(NSString*)text; +- (void)setEnabled:(BOOL)enabled; +- (void)resetPin; +- (IBAction)onApply:(id)sender; + +@end diff --git a/remoting/host/mac/me2me_preference_pane_confirm_pin.mm b/remoting/host/mac/me2me_preference_pane_confirm_pin.mm new file mode 100644 index 0000000..d83468a --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane_confirm_pin.mm @@ -0,0 +1,46 @@ +// 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 "remoting/host/mac/me2me_preference_pane_confirm_pin.h" + +@implementation Me2MePreferencePaneConfirmPin + +@synthesize delegate = delegate_; + +- (id)init { + self = [super initWithNibName:@"me2me_preference_pane_confirm_pin" + bundle:[NSBundle bundleForClass:[self class]]]; + return self; +} + +- (void)dealloc { + [delegate_ release]; + [super dealloc]; +} + +- (void)setEmail:(NSString*)email { + [email_ setStringValue:email]; +} + +- (void)setButtonText:(NSString*)text { + [apply_button_ setTitle:text]; +} + +- (void)setEnabled:(BOOL)enabled { + [apply_button_ setEnabled:enabled]; + [pin_ setEnabled:enabled]; + [[[self view] window] makeFirstResponder:pin_]; + [apply_button_ setKeyEquivalent:@"\r"]; +} + +- (void)resetPin { + [pin_ setStringValue:@""]; +} + +- (void)onApply:(id)sender { + [delegate_ applyConfiguration:self + pin:[pin_ stringValue]]; +} + +@end diff --git a/remoting/host/mac/me2me_preference_pane_confirm_pin.xib b/remoting/host/mac/me2me_preference_pane_confirm_pin.xib new file mode 100644 index 0000000..01814e5 --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane_confirm_pin.xib @@ -0,0 +1,472 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> + <data> + <int key="IBDocument.SystemTarget">1070</int> + <string key="IBDocument.SystemVersion">12C54</string> + <string key="IBDocument.InterfaceBuilderVersion">2549</string> + <string key="IBDocument.AppKitVersion">1187.34</string> + <string key="IBDocument.HIToolboxVersion">625.00</string> + <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="NS.object.0">2549</string> + </object> + <object class="NSArray" key="IBDocument.IntegratedClassDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSButton</string> + <string>NSButtonCell</string> + <string>NSCustomObject</string> + <string>NSCustomView</string> + <string>NSSecureTextField</string> + <string>NSSecureTextFieldCell</string> + <string>NSTextField</string> + <string>NSTextFieldCell</string> + </object> + <object class="NSArray" key="IBDocument.PluginDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + <object class="NSMutableDictionary" key="IBDocument.Metadata"> + <string key="NS.key.0">PluginDependencyRecalculationVersion</string> + <integer value="1" key="NS.object.0"/> + </object> + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSCustomObject" id="1001"> + <string key="NSClassName">Me2MePreferencePaneConfirmPin</string> + </object> + <object class="NSCustomObject" id="1003"> + <string key="NSClassName">FirstResponder</string> + </object> + <object class="NSCustomObject" id="1004"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSCustomView" id="533406559"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">268</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSButton" id="614032086"> + <reference key="NSNextResponder" ref="533406559"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{413, 37}, {98, 25}}</string> + <reference key="NSSuperview" ref="533406559"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="245716473"> + <int key="NSCellFlags">-2080374784</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">Apply</string> + <object class="NSFont" key="NSSupport" id="141416998"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">13</double> + <int key="NSfFlags">1044</int> + </object> + <reference key="NSControlView" ref="614032086"/> + <int key="NSButtonFlags">-2038153216</int> + <int key="NSButtonFlags2">163</int> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">400</int> + <int key="NSPeriodicInterval">75</int> + </object> + <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + </object> + <object class="NSSecureTextField" id="367717657"> + <reference key="NSNextResponder" ref="533406559"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{217, 39}, {188, 22}}</string> + <reference key="NSSuperview" ref="533406559"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSSecureTextFieldCell" key="NSCell" id="867461627"> + <int key="NSCellFlags">342884416</int> + <int key="NSCellFlags2">272630784</int> + <string key="NSContents"/> + <reference key="NSSupport" ref="141416998"/> + <reference key="NSControlView" ref="367717657"/> + <bool key="NSDrawsBackground">YES</bool> + <object class="NSColor" key="NSBackgroundColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textBackgroundColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MQA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">textColor</string> + <object class="NSColor" key="NSColor" id="469937612"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MAA</bytes> + </object> + </object> + <object class="NSArray" key="NSAllowedInputLocales"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSAllRomanInputSourcesLocaleIdentifier</string> + </object> + </object> + <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + </object> + <object class="NSTextField" id="48351972"> + <reference key="NSNextResponder" ref="533406559"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{17, 44}, {195, 17}}</string> + <reference key="NSSuperview" ref="533406559"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="315240963"> + <int key="NSCellFlags">68157504</int> + <int key="NSCellFlags2">71304192</int> + <string key="NSContents">PIN:</string> + <reference key="NSSupport" ref="141416998"/> + <reference key="NSControlView" ref="48351972"/> + <object class="NSColor" key="NSBackgroundColor" id="201615415"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlColor</string> + <object class="NSColor" key="NSColor"> + <int key="NSColorSpace">3</int> + <bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes> + </object> + </object> + <object class="NSColor" key="NSTextColor" id="167213699"> + <int key="NSColorSpace">6</int> + <string key="NSCatalogName">System</string> + <string key="NSColorName">controlTextColor</string> + <reference key="NSColor" ref="469937612"/> + </object> + </object> + <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + </object> + <object class="NSTextField" id="194991364"> + <reference key="NSNextResponder" ref="533406559"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{214, 69}, {402, 17}}</string> + <reference key="NSSuperview" ref="533406559"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="362759672"> + <int key="NSCellFlags">68157504</int> + <int key="NSCellFlags2">4195328</int> + <string key="NSContents">username</string> + <reference key="NSSupport" ref="141416998"/> + <reference key="NSControlView" ref="194991364"/> + <reference key="NSBackgroundColor" ref="201615415"/> + <reference key="NSTextColor" ref="167213699"/> + </object> + <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + </object> + <object class="NSTextField" id="511257665"> + <reference key="NSNextResponder" ref="533406559"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{17, 69}, {195, 17}}</string> + <reference key="NSSuperview" ref="533406559"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSTextFieldCell" key="NSCell" id="789178234"> + <int key="NSCellFlags">68157504</int> + <int key="NSCellFlags2">71304192</int> + <string key="NSContents">User:</string> + <reference key="NSSupport" ref="141416998"/> + <reference key="NSControlView" ref="511257665"/> + <reference key="NSBackgroundColor" ref="201615415"/> + <reference key="NSTextColor" ref="167213699"/> + </object> + <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + </object> + </object> + <string key="NSFrameSize">{633, 106}</string> + <reference key="NSSuperview"/> + <reference key="NSWindow"/> + <string key="NSClassName">NSCustomView</string> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">email_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="194991364"/> + </object> + <int key="connectionID">15</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">pin_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="367717657"/> + </object> + <int key="connectionID">16</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">view</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="533406559"/> + </object> + <int key="connectionID">18</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">onApply:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="614032086"/> + </object> + <int key="connectionID">21</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">apply_button_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="614032086"/> + </object> + <int key="connectionID">22</int> + </object> + </object> + <object class="IBMutableOrderedSet" key="objectRecords"> + <object class="NSArray" key="orderedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <object class="NSArray" key="object" id="0"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="children" ref="1000"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-2</int> + <reference key="object" ref="1001"/> + <reference key="parent" ref="0"/> + <string key="objectName">File's Owner</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-1</int> + <reference key="object" ref="1003"/> + <reference key="parent" ref="0"/> + <string key="objectName">First Responder</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-3</int> + <reference key="object" ref="1004"/> + <reference key="parent" ref="0"/> + <string key="objectName">Application</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">1</int> + <reference key="object" ref="533406559"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="48351972"/> + <reference ref="511257665"/> + <reference ref="367717657"/> + <reference ref="614032086"/> + <reference ref="194991364"/> + </object> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">4</int> + <reference key="object" ref="511257665"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="789178234"/> + </object> + <reference key="parent" ref="533406559"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">5</int> + <reference key="object" ref="789178234"/> + <reference key="parent" ref="511257665"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">6</int> + <reference key="object" ref="48351972"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="315240963"/> + </object> + <reference key="parent" ref="533406559"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">7</int> + <reference key="object" ref="315240963"/> + <reference key="parent" ref="48351972"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">8</int> + <reference key="object" ref="194991364"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="362759672"/> + </object> + <reference key="parent" ref="533406559"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">9</int> + <reference key="object" ref="362759672"/> + <reference key="parent" ref="194991364"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">10</int> + <reference key="object" ref="367717657"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="867461627"/> + </object> + <reference key="parent" ref="533406559"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">11</int> + <reference key="object" ref="867461627"/> + <reference key="parent" ref="367717657"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">19</int> + <reference key="object" ref="614032086"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="245716473"/> + </object> + <reference key="parent" ref="533406559"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">20</int> + <reference key="object" ref="245716473"/> + <reference key="parent" ref="614032086"/> + </object> + </object> + </object> + <object class="NSMutableDictionary" key="flattenedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>-1.IBPluginDependency</string> + <string>-2.IBPluginDependency</string> + <string>-3.IBPluginDependency</string> + <string>1.IBPluginDependency</string> + <string>10.IBPluginDependency</string> + <string>11.IBPluginDependency</string> + <string>19.IBPluginDependency</string> + <string>20.IBPluginDependency</string> + <string>4.IBPluginDependency</string> + <string>5.IBPluginDependency</string> + <string>6.IBPluginDependency</string> + <string>7.IBPluginDependency</string> + <string>8.IBPluginDependency</string> + <string>9.IBPluginDependency</string> + </object> + <object class="NSArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + </object> + <object class="NSMutableDictionary" key="unlocalizedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <reference key="dict.values" ref="0"/> + </object> + <nil key="activeLocalization"/> + <object class="NSMutableDictionary" key="localizations"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <reference key="dict.values" ref="0"/> + </object> + <nil key="sourceID"/> + <int key="maxID">22</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">Me2MePreferencePaneConfirmPin</string> + <string key="superclassName">NSViewController</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">onApply:</string> + <string key="NS.object.0">id</string> + </object> + <object class="NSMutableDictionary" key="actionInfosByName"> + <string key="NS.key.0">onApply:</string> + <object class="IBActionInfo" key="NS.object.0"> + <string key="name">onApply:</string> + <string key="candidateClassName">id</string> + </object> + </object> + <object class="NSMutableDictionary" key="outlets"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>apply_button_</string> + <string>email_</string> + <string>pin_</string> + </object> + <object class="NSArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSButton</string> + <string>NSTextField</string> + <string>NSTextField</string> + </object> + </object> + <object class="NSMutableDictionary" key="toOneOutletInfosByName"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>apply_button_</string> + <string>email_</string> + <string>pin_</string> + </object> + <object class="NSArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBToOneOutletInfo"> + <string key="name">apply_button_</string> + <string key="candidateClassName">NSButton</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">email_</string> + <string key="candidateClassName">NSTextField</string> + </object> + <object class="IBToOneOutletInfo"> + <string key="name">pin_</string> + <string key="candidateClassName">NSTextField</string> + </object> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/Me2MePreferencePaneConfirmPin.h</string> + </object> + </object> + </object> + </object> + <int key="IBDocument.localizationMode">0</int> + <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> + <real value="1070" key="NS.object.0"/> + </object> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string> + <integer value="3000" key="NS.object.0"/> + </object> + <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + </data> +</archive> diff --git a/remoting/host/mac/me2me_preference_pane_disable.h b/remoting/host/mac/me2me_preference_pane_disable.h new file mode 100644 index 0000000..9871e7c --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane_disable.h @@ -0,0 +1,20 @@ +// 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> + +// This view-controller holds just a "Disable" button. It is shown when the +// pref-pane is launched manually, or when the user has just confirmed their +// PIN and applied a new configuration. +@interface Me2MePreferencePaneDisable : NSViewController { + IBOutlet NSButton* disable_button_; + id delegate_; +} + +@property (retain) id delegate; + +- (void)setEnabled:(BOOL)enabled; +- (IBAction)onDisable:(id)sender; + +@end diff --git a/remoting/host/mac/me2me_preference_pane_disable.mm b/remoting/host/mac/me2me_preference_pane_disable.mm new file mode 100644 index 0000000..a2aa8b3 --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane_disable.mm @@ -0,0 +1,30 @@ +// 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 "remoting/host/mac/me2me_preference_pane_disable.h" + +@implementation Me2MePreferencePaneDisable + +@synthesize delegate = delegate_; + +- (id)init { + self = [super initWithNibName:@"me2me_preference_pane_disable" + bundle:[NSBundle bundleForClass:[self class]]]; + return self; +} + +- (void)dealloc { + [delegate_ release]; + [super dealloc]; +} + +- (void)setEnabled:(BOOL)enabled { + [disable_button_ setEnabled:enabled]; +} + +- (void)onDisable:(id)sender { + [delegate_ onDisable:self]; +} + +@end diff --git a/remoting/host/mac/me2me_preference_pane_disable.xib b/remoting/host/mac/me2me_preference_pane_disable.xib new file mode 100644 index 0000000..e8d23cc --- /dev/null +++ b/remoting/host/mac/me2me_preference_pane_disable.xib @@ -0,0 +1,242 @@ +<?xml version="1.0" encoding="UTF-8"?> +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10"> + <data> + <int key="IBDocument.SystemTarget">1070</int> + <string key="IBDocument.SystemVersion">12C54</string> + <string key="IBDocument.InterfaceBuilderVersion">2549</string> + <string key="IBDocument.AppKitVersion">1187.34</string> + <string key="IBDocument.HIToolboxVersion">625.00</string> + <object class="NSMutableDictionary" key="IBDocument.PluginVersions"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string> + <string key="NS.object.0">2549</string> + </object> + <object class="NSArray" key="IBDocument.IntegratedClassDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>NSButton</string> + <string>NSButtonCell</string> + <string>NSCustomObject</string> + <string>NSCustomView</string> + </object> + <object class="NSArray" key="IBDocument.PluginDependencies"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + <object class="NSMutableDictionary" key="IBDocument.Metadata"> + <string key="NS.key.0">PluginDependencyRecalculationVersion</string> + <integer value="1" key="NS.object.0"/> + </object> + <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSCustomObject" id="1001"> + <string key="NSClassName">Me2MePreferencePaneDisable</string> + </object> + <object class="NSCustomObject" id="1003"> + <string key="NSClassName">FirstResponder</string> + </object> + <object class="NSCustomObject" id="1004"> + <string key="NSClassName">NSApplication</string> + </object> + <object class="NSCustomView" id="533406559"> + <reference key="NSNextResponder"/> + <int key="NSvFlags">268</int> + <object class="NSMutableArray" key="NSSubviews"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSButton" id="3286585"> + <reference key="NSNextResponder" ref="533406559"/> + <int key="NSvFlags">268</int> + <string key="NSFrame">{{200, 62}, {232, 25}}</string> + <reference key="NSSuperview" ref="533406559"/> + <reference key="NSWindow"/> + <bool key="NSEnabled">YES</bool> + <object class="NSButtonCell" key="NSCell" id="1024006216"> + <int key="NSCellFlags">-2080374784</int> + <int key="NSCellFlags2">134217728</int> + <string key="NSContents">Disable Remote Connections</string> + <object class="NSFont" key="NSSupport"> + <string key="NSName">LucidaGrande</string> + <double key="NSSize">13</double> + <int key="NSfFlags">1044</int> + </object> + <reference key="NSControlView" ref="3286585"/> + <int key="NSButtonFlags">-2038153216</int> + <int key="NSButtonFlags2">163</int> + <string key="NSAlternateContents"/> + <string key="NSKeyEquivalent"/> + <int key="NSPeriodicDelay">400</int> + <int key="NSPeriodicInterval">75</int> + </object> + <bool key="NSAllowsLogicalLayoutDirection">NO</bool> + </object> + </object> + <string key="NSFrameSize">{633, 106}</string> + <reference key="NSSuperview"/> + <reference key="NSWindow"/> + <string key="NSClassName">NSCustomView</string> + </object> + </object> + <object class="IBObjectContainer" key="IBDocument.Objects"> + <object class="NSMutableArray" key="connectionRecords"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">view</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="533406559"/> + </object> + <int key="connectionID">16</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBOutletConnection" key="connection"> + <string key="label">disable_button_</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="3286585"/> + </object> + <int key="connectionID">21</int> + </object> + <object class="IBConnectionRecord"> + <object class="IBActionConnection" key="connection"> + <string key="label">onDisable:</string> + <reference key="source" ref="1001"/> + <reference key="destination" ref="3286585"/> + </object> + <int key="connectionID">22</int> + </object> + </object> + <object class="IBMutableOrderedSet" key="objectRecords"> + <object class="NSArray" key="orderedObjects"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBObjectRecord"> + <int key="objectID">0</int> + <object class="NSArray" key="object" id="0"> + <bool key="EncodedWithXMLCoder">YES</bool> + </object> + <reference key="children" ref="1000"/> + <nil key="parent"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-2</int> + <reference key="object" ref="1001"/> + <reference key="parent" ref="0"/> + <string key="objectName">File's Owner</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-1</int> + <reference key="object" ref="1003"/> + <reference key="parent" ref="0"/> + <string key="objectName">First Responder</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">-3</int> + <reference key="object" ref="1004"/> + <reference key="parent" ref="0"/> + <string key="objectName">Application</string> + </object> + <object class="IBObjectRecord"> + <int key="objectID">1</int> + <reference key="object" ref="533406559"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="3286585"/> + </object> + <reference key="parent" ref="0"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">19</int> + <reference key="object" ref="3286585"/> + <object class="NSMutableArray" key="children"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference ref="1024006216"/> + </object> + <reference key="parent" ref="533406559"/> + </object> + <object class="IBObjectRecord"> + <int key="objectID">20</int> + <reference key="object" ref="1024006216"/> + <reference key="parent" ref="3286585"/> + </object> + </object> + </object> + <object class="NSMutableDictionary" key="flattenedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="NSArray" key="dict.sortedKeys"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>-1.IBPluginDependency</string> + <string>-2.IBPluginDependency</string> + <string>-3.IBPluginDependency</string> + <string>1.IBPluginDependency</string> + <string>19.IBPluginDependency</string> + <string>20.IBPluginDependency</string> + </object> + <object class="NSArray" key="dict.values"> + <bool key="EncodedWithXMLCoder">YES</bool> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + <string>com.apple.InterfaceBuilder.CocoaPlugin</string> + </object> + </object> + <object class="NSMutableDictionary" key="unlocalizedProperties"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <reference key="dict.values" ref="0"/> + </object> + <nil key="activeLocalization"/> + <object class="NSMutableDictionary" key="localizations"> + <bool key="EncodedWithXMLCoder">YES</bool> + <reference key="dict.sortedKeys" ref="0"/> + <reference key="dict.values" ref="0"/> + </object> + <nil key="sourceID"/> + <int key="maxID">22</int> + </object> + <object class="IBClassDescriber" key="IBDocument.Classes"> + <object class="NSMutableArray" key="referencedPartialClassDescriptions"> + <bool key="EncodedWithXMLCoder">YES</bool> + <object class="IBPartialClassDescription"> + <string key="className">Me2MePreferencePaneDisable</string> + <string key="superclassName">NSViewController</string> + <object class="NSMutableDictionary" key="actions"> + <string key="NS.key.0">onDisable:</string> + <string key="NS.object.0">id</string> + </object> + <object class="NSMutableDictionary" key="actionInfosByName"> + <string key="NS.key.0">onDisable:</string> + <object class="IBActionInfo" key="NS.object.0"> + <string key="name">onDisable:</string> + <string key="candidateClassName">id</string> + </object> + </object> + <object class="NSMutableDictionary" key="outlets"> + <string key="NS.key.0">disable_button_</string> + <string key="NS.object.0">NSButton</string> + </object> + <object class="NSMutableDictionary" key="toOneOutletInfosByName"> + <string key="NS.key.0">disable_button_</string> + <object class="IBToOneOutletInfo" key="NS.object.0"> + <string key="name">disable_button_</string> + <string key="candidateClassName">NSButton</string> + </object> + </object> + <object class="IBClassDescriptionSource" key="sourceIdentifier"> + <string key="majorKey">IBProjectSource</string> + <string key="minorKey">./Classes/Me2MePreferencePaneDisable.h</string> + </object> + </object> + </object> + </object> + <int key="IBDocument.localizationMode">0</int> + <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDependencyDefaults"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.macosx</string> + <real value="1070" key="NS.object.0"/> + </object> + <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies"> + <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string> + <integer value="3000" key="NS.object.0"/> + </object> + <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool> + <int key="IBDocument.defaultPropertyAccessControl">3</int> + </data> +</archive> |