2
0

Improve lock/unlock assurance flow.

[FIXED]     Bug that caused the window to sometimes re-open when closed.
This commit is contained in:
Maarten Billemont 2013-06-09 19:03:54 -04:00
parent 797060f609
commit 08d3d9ad30
6 changed files with 80 additions and 92 deletions

View File

@ -225,7 +225,7 @@
<object class="NSButtonCell" key="NSCell" id="922307452"> <object class="NSButtonCell" key="NSCell" id="922307452">
<int key="NSCellFlags">67108864</int> <int key="NSCellFlags">67108864</int>
<int key="NSCellFlags2">134217728</int> <int key="NSCellFlags2">134217728</int>
<string key="NSContents">Enable iCloud</string> <string key="NSContents">Use iCloud</string>
<reference key="NSSupport" ref="1068244176"/> <reference key="NSSupport" ref="1068244176"/>
<string key="NSCellIdentifier">_NS:9</string> <string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="499448697"/> <reference key="NSControlView" ref="499448697"/>

View File

@ -204,7 +204,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
- (IBAction)terminate:(id)sender { - (IBAction)terminate:(id)sender {
NSLog( @"Closing: Terminating" );
[self.passwordWindow close]; [self.passwordWindow close];
self.passwordWindow = nil; self.passwordWindow = nil;
@ -215,7 +214,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://itunes.apple.com/app/id510296984"]]; [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://itunes.apple.com/app/id510296984"]];
NSLog( @"Closing: App Store" );
[self.initialWindow close]; [self.initialWindow close];
self.initialWindow = nil; self.initialWindow = nil;
} }
@ -271,7 +269,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
if (![self.passwordWindow.window isVisible]) if (![self.passwordWindow.window isVisible])
self.passwordWindow = nil; self.passwordWindow = nil;
else { else {
NSLog( @"Closing: dialogStyleHUD && passwordWindow.isVisible" );
[self.passwordWindow close]; [self.passwordWindow close];
self.passwordWindow = nil; self.passwordWindow = nil;
[self showPasswordWindow:nil]; [self showPasswordWindow:nil];
@ -305,8 +302,6 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
BOOL reopenPasswordWindow = [self.passwordWindow.window isVisible]; BOOL reopenPasswordWindow = [self.passwordWindow.window isVisible];
if (![[self activeUserForThread].objectID isEqual:activeUser.objectID]) { if (![[self activeUserForThread].objectID isEqual:activeUser.objectID]) {
NSLog( @"Closing: activeUser changed: %@ -> %@, reopening: %d", [self activeUserForThread].objectID, activeUser.objectID,
reopenPasswordWindow );
[self.passwordWindow close]; [self.passwordWindow close];
self.passwordWindow = nil; self.passwordWindow = nil;
[super setActiveUser:activeUser]; [super setActiveUser:activeUser];

View File

@ -17,7 +17,6 @@
@property(nonatomic, weak) IBOutlet NSProgressIndicator *progressView; @property(nonatomic, weak) IBOutlet NSProgressIndicator *progressView;
@property(nonatomic, weak) IBOutlet NSTextField *userLabel; @property(nonatomic, weak) IBOutlet NSTextField *userLabel;
- (void)unlock;
- (IBAction)reload:(id)sender; - (IBAction)reload:(id)sender;
@end @end

View File

@ -22,6 +22,7 @@
@property(nonatomic, strong) NSOperationQueue *backgroundQueue; @property(nonatomic, strong) NSOperationQueue *backgroundQueue;
@property(nonatomic, strong) NSAlert *loadingDataAlert; @property(nonatomic, strong) NSAlert *loadingDataAlert;
@property(nonatomic) BOOL closing;
@end @end
@implementation MPPasswordWindowController { @implementation MPPasswordWindowController {
@ -30,7 +31,6 @@
- (void)windowDidLoad { - (void)windowDidLoad {
NSLog(@"DidLoad:\n%@", [NSThread callStackSymbols]);
if ([[MPMacConfig get].dialogStyleHUD boolValue]) if ([[MPMacConfig get].dialogStyleHUD boolValue])
self.window.styleMask = NSHUDWindowMask | NSTitledWindowMask | NSUtilityWindowMask | NSClosableWindowMask; self.window.styleMask = NSHUDWindowMask | NSTitledWindowMask | NSUtilityWindowMask | NSClosableWindowMask;
else else
@ -52,73 +52,63 @@
// @"their passwords to change. You'll need to update your profile for that site with the new password."]; // @"their passwords to change. You'll need to update your profile for that site with the new password."];
// [moc saveToStore]; // [moc saveToStore];
// }]; // }];
[self handleUnloadedOrLocked]; [self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
} forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil]; } forKeyPath:@"key" options:NSKeyValueObservingOptionInitial context:nil];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil usingBlock:^(NSNotification *note) { addObserverForName:NSWindowDidBecomeKeyNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
NSLog(@"DidBecomeKey:\n%@", [NSThread callStackSymbols]); [self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
[self checkLoadedAndUnlocked];
[self.siteField selectText:nil]; [self.siteField selectText:nil];
}]; }];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserverForName:NSWindowWillCloseNotification object:self.window queue:nil usingBlock:^(NSNotification *note) { addObserverForName:NSWindowWillCloseNotification object:self.window queue:nil usingBlock:^(NSNotification *note) {
NSLog(@"WillClose:\n%@", [NSThread callStackSymbols]); dispatch_async( dispatch_get_main_queue(), ^{
NSWindow *sheet = [self.window attachedSheet]; NSWindow *sheet = [self.window attachedSheet];
if (sheet) if (sheet)
[NSApp endSheet:sheet]; [NSApp endSheet:sheet];
[NSApp hide:nil]; [NSApp hide:nil];
self.closing = NO;
} );
}]; }];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserverForName:MPSignedOutNotification object:nil queue:nil usingBlock:^(NSNotification *note) { addObserverForName:MPSignedOutNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
_activeElementOID = nil; _activeElementOID = nil;
[self.siteField setStringValue:@""]; [self.siteField setStringValue:@""];
[self trySiteWithAction:NO]; [self trySiteWithAction:NO];
[self handleUnloadedOrLocked]; [self ensureLoadedAndUnlockedOrCloseIfLoggedOut:YES];
}]; }];
[[NSNotificationCenter defaultCenter] [[NSNotificationCenter defaultCenter]
addObserverForName:USMStoreDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) { addObserverForName:USMStoreDidChangeNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
[self checkLoadedAndUnlocked]; [self ensureLoadedAndUnlockedOrCloseIfLoggedOut:NO];
}]; }];
[super windowDidLoad]; [super windowDidLoad];
} }
- (BOOL)shouldCloseDocument {
NSLog(@"shouldCloseDocument:\n%@", [NSThread callStackSymbols]);
return [super shouldCloseDocument];
}
- (void)close { - (void)close {
NSLog(@"close:\n%@", [NSThread callStackSymbols]);
self.closing = YES;
[super close]; [super close];
} }
- (void)handleUnloadedOrLocked { - (BOOL)ensureLoadedAndUnlockedOrCloseIfLoggedOut:(BOOL)closeIfLoggedOut {
if (!self.inProgress && ![MPMacAppDelegate get].key) { if (![self ensureStoreLoaded])
MPUserEntity *activeUser = [MPMacAppDelegate get].activeUserForThread; return NO;
if (activeUser && !activeUser.saveKey)
[self unlock]; if (self.closing || self.inProgress || !self.window.isKeyWindow)
else { return NO;
NSLog(@"Closing: !inProgress && !key && (!activeUser || activeUser.saveKey)");
[self.window close]; return [self ensureUnlocked:closeIfLoggedOut];
}
}
} }
- (void)checkLoadedAndUnlocked { - (BOOL)ensureStoreLoaded {
if ([self waitUntilStoreLoaded] && !self.inProgress)
[self unlock];
}
- (BOOL)waitUntilStoreLoaded {
if ([MPMacAppDelegate managedObjectContextForThreadIfReady]) { if ([MPMacAppDelegate managedObjectContextForThreadIfReady]) {
[NSApp endSheet:self.loadingDataAlert.window]; // Store loaded.
if (self.loadingDataAlert.window)
[NSApp endSheet:self.loadingDataAlert.window];
return YES; return YES;
} }
@ -130,43 +120,57 @@
return NO; return NO;
} }
- (void)unlock { - (BOOL)ensureUnlocked:(BOOL)closeIfLoggedOut {
[MPMacAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) { __block BOOL unlocked = NO;
[MPMacAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *moc) {
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc]; MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
NSString *userName = activeUser.name; NSString *userName = activeUser.name;
if (!activeUser) if (!activeUser) {
// No user to sign in with. // No user to sign in with.
if (closeIfLoggedOut)
[self close];
return; return;
if ([MPMacAppDelegate get].key) }
// Already logged in. if ([MPMacAppDelegate get].key) {
// Already logged in.
unlocked = YES;
return; return;
if ([[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc usingMasterPassword:nil]) }
// Load the key from the keychain. if (activeUser.saveKey && closeIfLoggedOut) {
// App was locked, don't instantly unlock again.
[self close];
return; return;
}
if ([[MPMacAppDelegate get] signInAsUser:activeUser saveInContext:moc usingMasterPassword:nil]) {
// Loaded the key from the keychain.
unlocked = YES;
return;
}
if (![MPMacAppDelegate get].key) // Ask the user to set the key through his master password.
// Ask the user to set the key through his master password. [[NSOperationQueue mainQueue] addOperationWithBlock:^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ if ([MPMacAppDelegate get].key)
if ([MPMacAppDelegate get].key) return;
return;
self.content = @""; self.content = @"";
[self.siteField setStringValue:@""]; [self.siteField setStringValue:@""];
[self.tipField setStringValue:@""]; [self.tipField setStringValue:@""];
NSAlert *alert = [NSAlert alertWithMessageText:@"Master Password is locked." NSAlert *alert = [NSAlert alertWithMessageText:@"Master Password is locked."
defaultButton:@"Unlock" alternateButton:@"Change" otherButton:@"Cancel" defaultButton:@"Unlock" alternateButton:@"Change" otherButton:@"Cancel"
informativeTextWithFormat:@"The master password is required to unlock the application for:\n\n%@", informativeTextWithFormat:@"The master password is required to unlock the application for:\n\n%@",
userName]; userName];
NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )]; NSSecureTextField *passwordField = [[NSSecureTextField alloc] initWithFrame:NSMakeRect( 0, 0, 200, 22 )];
[alert setAccessoryView:passwordField]; [alert setAccessoryView:passwordField];
[alert layout]; [alert layout];
[passwordField becomeFirstResponder]; [passwordField becomeFirstResponder];
[alert beginSheetModalForWindow:self.window modalDelegate:self [alert beginSheetModalForWindow:self.window modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP]; didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertUnlockMP];
}]; }];
}]; }];
return unlocked;
} }
- (IBAction)reload:(id)sender { - (IBAction)reload:(id)sender {
@ -177,8 +181,7 @@
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo { - (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
if (contextInfo == MPAlertIncorrectMP) { if (contextInfo == MPAlertIncorrectMP) {
NSLog(@"Closing: Incorrect MP, button: %ld", returnCode); [self close];
[self.window close];
return; return;
} }
if (contextInfo == MPAlertUnlockMP) { if (contextInfo == MPAlertUnlockMP) {
@ -209,9 +212,8 @@
case NSAlertOtherReturn: { case NSAlertOtherReturn: {
// "Cancel" button. // "Cancel" button.
NSLog(@"Closing: Unlock MP, button: %ld", (long)returnCode); [self close];
[self.window close]; break;
return;
} }
case NSAlertDefaultReturn: { case NSAlertDefaultReturn: {
@ -228,7 +230,7 @@
usingMasterPassword:password]; usingMasterPassword:password];
self.inProgress = NO; self.inProgress = NO;
[[NSOperationQueue mainQueue] addOperationWithBlock:^{ dispatch_async( dispatch_get_current_queue(), ^{
[self.progressView stopAnimation:nil]; [self.progressView stopAnimation:nil];
if (success) if (success)
@ -239,7 +241,7 @@
}]] beginSheetModalForWindow:self.window modalDelegate:self }]] beginSheetModalForWindow:self.window modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP]; didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) contextInfo:MPAlertIncorrectMP];
} }
}]; } );
}]; }];
break; break;
} }
@ -307,8 +309,7 @@
- (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector { - (BOOL)control:(NSControl *)control textView:(NSTextView *)fieldEditor doCommandBySelector:(SEL)commandSelector {
if (commandSelector == @selector(cancel:)) { // Escape without completion. if (commandSelector == @selector(cancel:)) { // Escape without completion.
NSLog(@"Closing: ESC without completion"); [self close];
[self.window close];
return YES; return YES;
} }
if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"])) { // Backspace any time. if ((self.siteFieldPreventCompletion = [NSStringFromSelector( commandSelector ) hasPrefix:@"delete"])) { // Backspace any time.
@ -399,7 +400,6 @@
if (!content) if (!content)
content = @""; content = @"";
dbg(@"name: %@, action: %d", siteName, doAction);
if (doAction) { if (doAction) {
if ([content length]) { if ([content length]) {
// Performing action while content is available. Copy it. // Performing action while content is available. Copy it.

View File

@ -15,7 +15,7 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E" BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
BuildableName = "MasterPassword.app" BuildableName = "Master Password.app"
BlueprintName = "MasterPassword" BlueprintName = "MasterPassword"
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj"> ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
</BuildableReference> </BuildableReference>
@ -43,7 +43,7 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E" BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
BuildableName = "MasterPassword.app" BuildableName = "Master Password.app"
BlueprintName = "MasterPassword" BlueprintName = "MasterPassword"
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj"> ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
</BuildableReference> </BuildableReference>

View File

@ -15,7 +15,7 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E" BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
BuildableName = "MasterPassword.app" BuildableName = "Master Password.app"
BlueprintName = "MasterPassword" BlueprintName = "MasterPassword"
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj"> ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
</BuildableReference> </BuildableReference>
@ -43,17 +43,11 @@
<BuildableReference <BuildableReference
BuildableIdentifier = "primary" BuildableIdentifier = "primary"
BlueprintIdentifier = "DA5BFA43147E415C00F98B1E" BlueprintIdentifier = "DA5BFA43147E415C00F98B1E"
BuildableName = "MasterPassword.app" BuildableName = "Master Password.app"
BlueprintName = "MasterPassword" BlueprintName = "MasterPassword"
ReferencedContainer = "container:MasterPassword-Mac.xcodeproj"> ReferencedContainer = "container:MasterPassword-Mac.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
<CommandLineArguments>
<CommandLineArgument
argument = "-com.apple.coredata.ubiquity.logLevel 3"
isEnabled = "NO">
</CommandLineArgument>
</CommandLineArguments>
<EnvironmentVariables> <EnvironmentVariables>
<EnvironmentVariable <EnvironmentVariable
key = "CA_DEBUG_TRANSACTIONS" key = "CA_DEBUG_TRANSACTIONS"