Created status bar icon with menu.
[pithos-macos] / pithos-macos / pithos_macosAppDelegate.m
1 //
2 //  pithos_macosAppDelegate.m
3 //  pithos-macos
4 //
5 // Copyright 2011 GRNET S.A. All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or
8 // without modification, are permitted provided that the following
9 // conditions are met:
10 // 
11 //   1. Redistributions of source code must retain the above
12 //      copyright notice, this list of conditions and the following
13 //      disclaimer.
14 // 
15 //   2. Redistributions in binary form must reproduce the above
16 //      copyright notice, this list of conditions and the following
17 //      disclaimer in the documentation and/or other materials
18 //      provided with the distribution.
19 // 
20 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 // 
33 // The views and conclusions contained in the software and
34 // documentation are those of the authors and should not be
35 // interpreted as representing official policies, either expressed
36 // or implied, of GRNET S.A.
37
38 #import "pithos_macosAppDelegate.h"
39 #import "PithosBrowserController.h"
40 #import "PithosPreferencesController.h"
41 #import "ASIPithosRequest.h"
42
43 @implementation pithos_macosAppDelegate
44
45 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
46     [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self 
47                                                        andSelector:@selector(handleAppleEvent:withReplyEvent:) 
48                                                      forEventClass:kInternetEventClass 
49                                                         andEventID:kAEGetURL];
50     //[pithosBrowserController showWindow:self];
51     [self showPithosBrowser:self];
52     
53     [self authenticateWithAuthUser:[[userDefaultsController values] valueForKey:@"authUser"] 
54                          authToken:[[userDefaultsController values] valueForKey:@"authToken"]];
55 }
56
57 // Based on: http://cocoatutorial.grapewave.com/2010/01/creating-a-status-bar-application/
58 // and: http://www.cocoadev.com/index.pl?ThumbnailImages
59 - (void)awakeFromNib {
60     NSImage *sourceImage = [NSImage imageNamed:NSImageNameFolder];
61     
62     NSImage *smallImage = [[[NSImage alloc] initWithSize:NSMakeSize(18, 18)] autorelease];
63     [smallImage lockFocus];
64     [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh];
65     [sourceImage setSize:NSMakeSize(18, 18)];
66     [sourceImage compositeToPoint:NSZeroPoint operation:NSCompositeCopy];
67     [smallImage unlockFocus];
68     
69     statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
70     [statusItem setMenu:statusMenu];
71     [statusItem setImage:sourceImage];
72     [statusItem setHighlightMode:YES];
73 }
74
75 - (void)handleAppleEvent:(NSAppleEventDescriptor *)event withReplyEvent: (NSAppleEventDescriptor *)replyEvent {
76     NSURL *url = [NSURL URLWithString:[[event paramDescriptorForKeyword:keyDirectObject] stringValue]];
77     NSString *host = [url host];
78         NSString *query = [url query];
79     NSLog(@"host : '%@', query: '%@'", host, query);
80     NSProcessInfo *processInfo = [NSProcessInfo processInfo];
81     if ([host isEqualToString:[NSString stringWithFormat:@"%@_%d", [processInfo processName], [processInfo processIdentifier]]] && query) {
82         // user=
83         NSString *authUser;
84         NSRange userRange = [query rangeOfString:@"user=" options:NSCaseInsensitiveSearch];
85         if (userRange.length == 0)
86             // XXX maybe show an error message?
87             return;
88         NSUInteger authUserStartLocation = userRange.location + userRange.length;
89         NSRange userEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch 
90                                               range:NSMakeRange(authUserStartLocation, [query length] - authUserStartLocation)];
91         if (userEndRange.length) {
92             authUser = [[query substringWithRange:NSMakeRange(authUserStartLocation, userEndRange.location - authUserStartLocation)]
93                         stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
94         } else {
95             authUser = [[query substringFromIndex:authUserStartLocation]
96                         stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
97         }
98         // token=
99         NSString *authToken;
100         NSRange tokenRange = [query rangeOfString:@"token=" options:NSCaseInsensitiveSearch];
101         if (tokenRange.length == 0)
102             // XXX maybe show an error message?
103             return;
104         NSUInteger authTokenStartLocation = tokenRange.location + tokenRange.length;
105         NSRange tokenEndRange = [query rangeOfString:@"&" options:NSCaseInsensitiveSearch 
106                                               range:NSMakeRange(authTokenStartLocation, [query length] - authTokenStartLocation)];
107         if (tokenEndRange.length) {
108             authToken = [[query substringWithRange:NSMakeRange(authTokenStartLocation, tokenEndRange.location - authTokenStartLocation)]
109                          stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
110         } else {
111             authToken = [[query substringFromIndex:authTokenStartLocation]
112                          stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
113         }
114         
115         NSLog(@"query authUser: '%@', authToken: '%@'", authUser, authToken);
116         if ([authUser length] && [authToken length]) {
117             [[userDefaultsController values] setValue:authUser forKey:@"authUser"];
118             [[userDefaultsController values] setValue:authToken forKey:@"authToken"];
119             
120             [self authenticateWithAuthUser:authUser authToken:authToken];
121         }
122         // XXX else maybe show an error message?
123     }
124     // XXX else maybe show an error message?
125 }
126
127 #pragma mark -
128 #pragma Actions
129
130 - (IBAction)showPithosBrowser:(id)sender {
131     [pithosBrowserController showWindow:sender];
132     [[pithosBrowserController window] makeKeyAndOrderFront:sender];
133     [NSApp activateIgnoringOtherApps:YES];
134 }
135
136 - (IBAction)showPithosPreferences:(id)sender {
137     [pithosPreferencesController showWindow:sender];
138     [[pithosPreferencesController window] makeKeyAndOrderFront:sender];
139     [NSApp activateIgnoringOtherApps:YES];
140 }
141
142 - (IBAction)aboutPithos:(id)sender {
143     [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://pithos.dev.grnet.gr/docs"]];
144 }
145
146 #pragma mark -
147 #pragma Authentication
148
149 - (void)authenticateWithAuthUser:(NSString *)authUser authToken:(NSString *)authToken {
150     // XXX hardcoded for now
151     NSString *storageURLPrefix = @"https://pithos.dev.grnet.gr/v1/";
152     
153     NSLog(@"Authentication - storageURLPrefix:%@, authUser:%@, authToken:%@", storageURLPrefix, authUser, authToken);
154     if ([authUser length] && [authToken length]) {
155         [ASIPithosRequest setStorageURL:[storageURLPrefix stringByAppendingString:[authUser stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
156         [ASIPithosRequest setAuthToken:authToken];
157         
158         [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosAuthenticationCredentialsUpdated" object:self];
159     }
160 }
161
162 @end