blob: 34ef2d0e35bd27a93c01f28f2bf484ff7253a966 [file] [log] [blame]
Alexander Afanasyev14b09482013-10-11 18:24:45 +02001/* -*- Mode: obj; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -07002/*
3 * @copyright See LICENCE for copyright and license information.
4 *
5 * @author Alexander Afanasyev <alexander.afanasyev@ucla.edu>
6 * @author Ilya Moiseenko <iliamo@ucla.edu>
7 */
8
Alexander Afanasyev2beff7f2013-09-27 17:50:36 -07009#include "config.h"
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070010#import "menu-delegate.h"
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070011#import "ndnd-status-operation.h"
Ilya Moiseenko2dffcf52013-09-27 15:08:04 -070012
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070013@implementation MenuDelegate
14
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070015-(id)init
16{
17 if (![super init]) {
18 return nil;
19 }
20
Alexander Afanasyevb9024d12013-10-14 18:10:18 +030021 m_autoconfInProgress = false;
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070022 m_operationQueue = [[NSOperationQueue alloc] init];
23 return self;
24}
25
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070026- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
27{
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -070028 // Register the preference defaults early.
29 NSDictionary *appDefaults =
30 [NSDictionary dictionaryWithObjectsAndKeys:
31 [NSNumber numberWithBool:YES], @"allowSoftwareUpdates",
32 [NSNumber numberWithBool:YES], @"enableHubDiscovery",
33 [NSNumber numberWithBool:NO], @"shutdownNdndOnExit",
34 nil
35 ];
36 [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
37
38 // Other initialization...
39
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070040 m_daemonStarted = false;
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070041
42 NSBundle *bundle = [NSBundle bundleForClass:[self class]];
43 m_connectedIcon = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"FlatConnected" ofType:@"png"]];
44 m_disconnectedIcon = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"FlatDisconnected" ofType:@"png"]];
45 m_statusXslt = [NSData dataWithContentsOfFile:[bundle pathForResource:@"status" ofType:@"xslt"]];
Ilya Moiseenkob4aca052013-10-06 15:10:19 -070046 m_statusToFibXslt = [NSData dataWithContentsOfFile:[bundle pathForResource:@"status-to-fib" ofType:@"xslt"]];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -070047
Alexander Afanasyevb9024d12013-10-14 18:10:18 +030048 [NSTimer scheduledTimerWithTimeInterval: 1.0
49 target: self
50 selector:@selector(onTick:)
51 userInfo: nil
52 repeats:YES];
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020053 [self updateStatus];
Alexander Afanasyev17922872013-10-15 11:45:58 +030054
55 m_systemEvents = [[SystemEvents alloc] init];
56}
57
58- (void)applicationWillTerminate:(NSNotification *)aNotification
59{
60 [m_systemEvents disable];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070061}
62
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070063-(void)awakeFromNib
64{
65 statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070066 [statusItem setMenu:statusMenu];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070067 [statusItem setToolTip:@"NDN Control Center"];
68 [statusItem setEnabled:YES];
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -070069 [statusItem setHighlightMode:YES];
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070070 //[statusItem setTarget:self];
71
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070072 [statusItem setTitle:@""];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070073 [statusItem setImage:m_disconnectedIcon];
Ilya Moiseenko01264322013-09-26 15:34:21 -070074
Ilya Moiseenko01264322013-09-26 15:34:21 -070075 [connectionStatus setView: connectionStatusView];
76 [connectionStatus setTarget:self];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070077
Ilya Moiseenko01264322013-09-26 15:34:21 -070078 [daemonStatus setView: daemonStatusView];
79 [daemonStatus setTarget:self];
Ilya Moiseenkoa10ef8d2013-09-25 17:23:05 -070080}
81
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070082-(IBAction)openDaemonStatus:(id)sender
83{
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070084}
85
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -070086-(IBAction)showExitConfirmationWindow:(id)sender
Ilya Moiseenko350b9b52013-09-25 16:38:41 -070087{
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -070088 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"shutdownNdndOnExit"]) {
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070089 [m_operationQueue cancelAllOperations];
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +020090
91 [m_operationQueue addOperationWithBlock:^{
92 NSTask *task = [[NSTask alloc] init];
93 [task setLaunchPath: @NDND_STOP_COMMAND];
94 [task launch];
95 [task waitUntilExit];
96 }];
97
98 [m_operationQueue waitUntilAllOperationsAreFinished];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -070099 [NSApp terminate:self];
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700100 }
101 else {
102 NSAlert *alert = [[NSAlert alloc] init];
103 [alert addButtonWithTitle:@"Yes"];
104 [alert addButtonWithTitle:@"No"];
105 [alert addButtonWithTitle:@"Cancel"];
106 [alert setMessageText:@"Shutdown NDN daemon as well?"];
107 [alert setInformativeText:@"All NDN operations will be become unavailable."];
108 [alert setAlertStyle:NSCriticalAlertStyle];
109 // [alert setShowsSuppressionButton: YES];
110
111 NSInteger res = [alert runModal];
112 if (res == NSAlertFirstButtonReturn) {
113 // "YES" stop ndnd
114 [m_operationQueue cancelAllOperations];
115
116 [m_operationQueue addOperationWithBlock:^{
117 NSTask *task = [[NSTask alloc] init];
118 [task setLaunchPath: @NDND_STOP_COMMAND];
119 [task launch];
120 [task waitUntilExit];
121 }];
122
123 [m_operationQueue waitUntilAllOperationsAreFinished];
124 [NSApp terminate:self];
125 } else if (res == NSAlertSecondButtonReturn) {
126 // "NO" terminate app but keep ndnd running
127 [m_operationQueue cancelAllOperations];
128 [NSApp terminate:self];
129 }
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700130 }
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -0700131}
132
Ilya Moiseenko01264322013-09-26 15:34:21 -0700133-(void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item
134{
Ilya Moiseenko01264322013-09-26 15:34:21 -0700135 if( ([item view]!=nil) && (item == daemonStatus) )
136 {
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700137 NSView *view = [item view];
138
139 [statusPopover showRelativeToRect:[view bounds]
140 ofView:view
141 preferredEdge:NSMinXEdge];
Ilya Moiseenko01264322013-09-26 15:34:21 -0700142 }
143 else
144 {
145 [statusPopover performClose:nil];
146 }
147}
148
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700149-(void)onTick:(NSTimer *)timer
150{
Alexander Afanasyev4e1c7e92013-10-11 18:25:09 +0200151 [self updateStatus];
152}
153
154-(void)updateStatus
155{
156 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
157 [m_operationQueue addOperation:operation];
158}
159
160-(void)updateStatusWithDependency:(NSOperation*)dependency
161{
162 NSOperation *operation = [[NdndStatusOperation alloc] initWithDelegate:self];
163 [operation addDependency:dependency];
164
165 [m_operationQueue addOperation:dependency];
166 [m_operationQueue addOperation:operation];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700167}
168
169- (void)statusUpdated:(NSXMLDocument*)document
170{
171 if (!m_daemonStarted) {
172 m_daemonStarted = true;
173 [connectionStatusText setStringValue:@"Active"];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700174
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700175 [statusItem setImage:m_connectedIcon];
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700176 }
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700177
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700178 NSXMLDocument *statusXml = [document objectByApplyingXSLT:m_statusXslt
179 arguments:nil
180 error:nil];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700181
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700182 NSXMLDocument *statusFibXml = [document objectByApplyingXSLT:m_statusToFibXslt
183 arguments:nil
184 error:nil];
185
186 m_statusString = [[NSAttributedString alloc]initWithHTML:[statusXml XMLData] documentAttributes:NULL];
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700187 [daemonStatusHtml setAttributedStringValue:m_statusString];
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700188
189 [preferencesDelegate updateFibStatus:statusFibXml];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300190
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700191 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableHubDiscovery"]) {
192 NSArray *autoconf = [[statusFibXml rootElement] nodesForXPath:@"//fib/prefix[text()='ndn:/autoconf-route']" error:nil];
193 if ([autoconf count] == 0)
194 {
195 [self restartDaemon:nil];
196 }
197 }
Ilya Moiseenko6d4086c2013-09-27 16:56:02 -0700198}
199
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700200- (void)statusUnavailable:(id)none
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700201{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700202 // try start ndnd if it is not started yet
203 if (m_daemonStarted) {
204 m_daemonStarted = false;
205
206 [connectionStatusText setStringValue:@"Starting..."];
207
208 [statusItem setImage:m_disconnectedIcon];
209 }
Ilya Moiseenkob4aca052013-10-06 15:10:19 -0700210
211 [daemonStatusHtml setStringValue:@""];
212 [preferencesDelegate updateFibStatus:nil];
213
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300214 m_autoconfInProgress = true;
215
216 NSOperation *startOp = [NSBlockOperation blockOperationWithBlock:^{
Alexander Afanasyev6cacb972013-10-03 23:39:06 -0700217 NSTask *task = [[NSTask alloc] init];
218 [task setLaunchPath: @NDND_START_COMMAND];
219 [task launch];
220 }];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300221
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700222 if ([[NSUserDefaults standardUserDefaults] boolForKey:@"enableHubDiscovery"]) {
223 NSOperation *autoconfOp = [NSBlockOperation blockOperationWithBlock:^{
224 NSTask *task = [[NSTask alloc] init];
225 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
226 [task launch];
227 [task waitUntilExit];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300228
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700229 m_autoconfInProgress = false;
230 }];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300231
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700232 [autoconfOp addDependency:startOp];
233 [m_operationQueue addOperation:autoconfOp];
234 }
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300235
236 [m_operationQueue addOperation:startOp];
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300237}
238
239-(void)restartDaemon:(id)none
240{
Alexander Afanasyev1d794ce2013-10-22 12:48:30 -0700241 if (![[NSUserDefaults standardUserDefaults] boolForKey:@"enableHubDiscovery"])
242 return;
243
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300244 if (m_autoconfInProgress)
245 return;
246
Alexander Afanasyev17922872013-10-15 11:45:58 +0300247 NSLog (@"No automatically detected route configured, trying to get one");
248
Alexander Afanasyevb9024d12013-10-14 18:10:18 +0300249 m_autoconfInProgress = true;
250 [m_operationQueue addOperationWithBlock:^{
251 NSTask *task = [[NSTask alloc] init];
252 [task setLaunchPath: @NDND_AUTOCONFIG_COMMAND];
253 [task launch];
254 [task waitUntilExit];
255
256 m_autoconfInProgress = false;
257 }];
Ilya Moiseenkoe7058e72013-10-02 15:56:45 -0700258}
259
Alexander Afanasyev88f0b3a2013-09-24 23:52:08 -0700260@end