1/*
2 * Copyright (c) 2012-2013 Apple Computer, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24//
25//  CKDUserInteraction.m
26//  CloudKeychainProxy
27//
28
29#import <CoreFoundation/CFUserNotification.h>
30#import <utilities/debugging.h>
31
32#import "CKDUserInteraction.h"
33#import "SOSARCDefines.h"
34
35static CKDUserInteraction *sharedInstance = nil;
36static CKDUserInteractionBlock completion;
37
38#define XPROXYUISCOPE "proxy-ui"
39
40static void userNotificationCallback(CFUserNotificationRef userNotification, CFOptionFlags responseFlags)
41{
42
43/*
44    kCFUserNotificationDefaultResponse		= 0,
45    kCFUserNotificationAlternateResponse	= 1,
46    kCFUserNotificationOtherResponse		= 2,
47    kCFUserNotificationCancelResponse		= 3
48*/
49
50    CKDUserInteraction *sharedInstance = [CKDUserInteraction sharedInstance];
51    CFDictionaryRef userResponses = CFUserNotificationGetResponseDictionary(userNotification);
52		// CFOptionFlags are poorly named, since it's a single response value, not a mask
53
54	secdebug(XPROXYUISCOPE, "sharedInstance: %@, rlsr: %@", sharedInstance, sharedInstance.runLoopSourceRef);
55	secdebug(XPROXYUISCOPE, "userNotification responses: %@, flags: %#lx",userResponses, responseFlags);
56
57    if (sharedInstance.runLoopSourceRef)
58        CFRunLoopRemoveSource(CFRunLoopGetMain(), sharedInstance.runLoopSourceRef, kCFRunLoopDefaultMode);
59
60    if (completion)  // sharedInstance.completion
61	{
62        secdebug(XPROXYUISCOPE, "Calling user completion routine");
63        completion(userResponses, responseFlags);   // sharedInstance.completion
64    }
65
66    secdebug(XPROXYUISCOPE, "Releasing user completion routine");
67//    Block_release(completion);   // sharedInstance.completion
68
69/*
70       if (responseFlags & kCFUserNotificationCancelResponse) {
71                returnCode = kABNotifierUserCancelled;
72        } else {
73                fUsername = (CFStringRef)CFUserNotificationGetResponseValue(notification, kCFUserNotificationTextFieldValuesKey, 0);
74                if(fUsername) CFRetain(fUsername);
75
76                fPassword = (CFStringRef)CFUserNotificationGetResponseValue(notification, kCFUserNotificationTextFieldValuesKey, 1);
77                if(fPassword) CFRetain(fPassword);
78
79                if((response & CFUserNotificationCheckBoxChecked(0)))
80*/
81
82//    if (responseFlags == kCFUserNotificationCancelResponse || responseFlags == kCFUserNotificationDefaultResponse)
83    CFRunLoopStop(CFRunLoopGetCurrent());
84	secdebug(XPROXYUISCOPE, "exit");
85}
86
87@implementation CKDUserInteraction
88
89+ (CKDUserInteraction *) sharedInstance
90{
91    if (!sharedInstance)
92		sharedInstance = [[self alloc] init];
93
94    return sharedInstance;
95}
96
97- (void)requestShowNotification:(NSDictionary *)infoForUserInfo completion:(CKDUserInteractionBlock)completionf
98{
99    __block CFOptionFlags flags = kCFUserNotificationCautionAlertLevel | kCFUserNotificationNoDefaultButtonFlag;
100    CFTimeInterval timeout = 30.0;
101
102//  completion = Block_copy(completionf);
103    completion = completionf;
104
105    CFStringRef headerStr = (__bridge CFStringRef)([infoForUserInfo objectForKey:(__bridge id)kCFUserNotificationAlertHeaderKey]);
106
107    CFStringRef cancelStr = CFSTR("No way"); //CFStringCreateWithCString(kCFAllocatorDefault, cancel.c_str(), kCFStringEncodingUTF8);
108    CFStringRef defaultStr = CFSTR("Sure"); //CFStringCreateWithCString(kCFAllocatorDefault, settings.c_str(), kCFStringEncodingUTF8);
109
110    CFMutableDictionaryRef notifyDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
111
112    // Header and buttons
113    CFDictionarySetValue(notifyDictionary, kCFUserNotificationAlertHeaderKey, headerStr);
114    CFDictionarySetValue(notifyDictionary, kCFUserNotificationDefaultButtonTitleKey, defaultStr);
115    CFDictionarySetValue(notifyDictionary, kCFUserNotificationAlternateButtonTitleKey, cancelStr);
116
117    SInt32 error = 0;
118    _userNotificationRef = CFUserNotificationCreate(kCFAllocatorDefault, timeout, flags, &error, notifyDictionary);
119
120    if (_userNotificationRef)
121    {
122        _runLoopSourceRef = CFUserNotificationCreateRunLoopSource(kCFAllocatorDefault, _userNotificationRef, userNotificationCallback, 0);
123        CFRunLoopAddSource(CFRunLoopGetMain(), _runLoopSourceRef, kCFRunLoopDefaultMode);
124	}
125
126}
127
128@end
129
130