Merge branch 'pu/pb/index_quick_fix' into stable
[GitX.git] / PBWebController.m
blobd185593c7c52c1d6d9690a9337013edbf0dc9d59
1 //
2 //  PBWebController.m
3 //  GitX
4 //
5 //  Created by Pieter de Bie on 08-10-08.
6 //  Copyright 2008 __MyCompanyName__. All rights reserved.
7 //
9 #import "PBWebController.h"
10 #import "PBGitRepository.h"
11 #import "PBGitXProtocol.h"
12 #import "PBGitDefaults.h"
14 #include <SystemConfiguration/SCNetworkReachability.h>
16 @interface PBWebController()
17 - (void)preferencesChangedWithNotification:(NSNotification *)theNotification;
18 @end
20 @implementation PBWebController
22 @synthesize startFile, repository;
24 - (void) awakeFromNib
26         NSString *path = [NSString stringWithFormat:@"html/views/%@", startFile];
27         NSString* file = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html" inDirectory:path];
28         NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL fileURLWithPath:file]];
29         callbacks = [NSMapTable mapTableWithKeyOptions:(NSPointerFunctionsObjectPointerPersonality|NSPointerFunctionsStrongMemory) valueOptions:(NSPointerFunctionsObjectPointerPersonality|NSPointerFunctionsStrongMemory)];
31         NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
32         [nc addObserver:self
33                selector:@selector(preferencesChangedWithNotification:)
34                    name:NSUserDefaultsDidChangeNotification
35                  object:nil];
37         finishedLoading = NO;
38         [view setUIDelegate:self];
39         [view setFrameLoadDelegate:self];
40         [view setResourceLoadDelegate:self];
41         [[view mainFrame] loadRequest:request];
44 - (WebScriptObject *) script
46         return [view windowScriptObject];
49 - (void) closeView
51         if (view)
52                 [view close];
55 # pragma mark Delegate methods
57 - (void)webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)windowObject forFrame:(WebFrame *)frame
59         id script = [view windowScriptObject];
60         [script setValue: self forKey:@"Controller"];
63 - (void) webView:(id) v didFinishLoadForFrame:(id) frame
65         finishedLoading = YES;
66         if ([self respondsToSelector:@selector(didLoad)])
67                 [self performSelector:@selector(didLoad)];
70 - (void)webView:(WebView *)webView addMessageToConsole:(NSDictionary *)dictionary
72         NSLog(@"Error from webkit: %@", dictionary);
75 - (NSURLRequest *)webView:(WebView *)sender
76                  resource:(id)identifier
77           willSendRequest:(NSURLRequest *)request
78          redirectResponse:(NSURLResponse *)redirectResponse
79            fromDataSource:(WebDataSource *)dataSource
81         if (!self.repository)
82                 return request;
84         // TODO: Change this to canInitWithRequest
85         if ([[[request URL] scheme] isEqualToString:@"GitX"]) {
86                 NSMutableURLRequest *newRequest = [request mutableCopy];
87                 [newRequest setRepository:self.repository];
88                 return newRequest;
89         }
91         return request;
95 + (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
97         return NO;
100 + (BOOL)isKeyExcludedFromWebScript:(const char *)name {
101         return NO;
104 #pragma mark Functions to be used from JavaScript
106 - (void) log: (NSString*) logMessage
108         NSLog(@"%@", logMessage);
111 - (BOOL) isReachable:(NSString *)hostname
113         SCNetworkConnectionFlags flags;
114         if (!SCNetworkCheckReachabilityByName([hostname cStringUsingEncoding:NSASCIIStringEncoding], &flags))
115                 return FALSE;
117         // If a connection is required, then it's not reachable
118         if (flags & (kSCNetworkFlagsConnectionRequired | kSCNetworkFlagsConnectionAutomatic | kSCNetworkFlagsInterventionRequired))
119                 return FALSE;
121         return flags > 0;
124 - (BOOL) isFeatureEnabled:(NSString *)feature
126         if([feature isEqualToString:@"gravatar"])
127                 return [PBGitDefaults isGravatarEnabled];
128         else if([feature isEqualToString:@"gist"])
129                 return [PBGitDefaults isGistEnabled];
130         else if([feature isEqualToString:@"confirmGist"])
131                 return [PBGitDefaults confirmPublicGists];
132         else if([feature isEqualToString:@"publicGist"])
133                 return [PBGitDefaults isGistPublic];
134         else
135                 return YES;
138 #pragma mark Using async function from JS
140 - (void) runCommand:(WebScriptObject *)arguments inRepository:(PBGitRepository *)repo callBack:(WebScriptObject *)callBack
142         // The JS bridge does not handle JS Arrays, even though the docs say it does. So, we convert it ourselves.
143         int length = [[arguments valueForKey:@"length"] intValue];
144         NSMutableArray *realArguments = [NSMutableArray arrayWithCapacity:length];
145         int i = 0;
146         for (i = 0; i < length; i++)
147                 [realArguments addObject:[arguments webScriptValueAtIndex:i]];
149         NSFileHandle *handle = [repo handleInWorkDirForArguments:realArguments];
150         [callbacks setObject:callBack forKey:handle];
151         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(JSRunCommandDone:) name:NSFileHandleReadToEndOfFileCompletionNotification object:handle]; 
152         [handle readToEndOfFileInBackgroundAndNotify];
155 - (void) callSelector:(NSString *)selectorString onObject:(id)object callBack:(WebScriptObject *)callBack
157         NSArray *arguments = [NSArray arrayWithObjects:selectorString, object, nil];
158         NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(runInThread:) object:arguments];
159         [callbacks setObject:callBack forKey:thread];
160         [thread start];
163 - (void) runInThread:(NSArray *)arguments
165         SEL selector = NSSelectorFromString([arguments objectAtIndex:0]);
166         id object = [arguments objectAtIndex:1];
167         id ret = [object performSelector:selector];
168         NSArray *returnArray = [NSArray arrayWithObjects:[NSThread currentThread], ret, nil];
169         [self performSelectorOnMainThread:@selector(threadFinished:) withObject:returnArray waitUntilDone:NO];
173 - (void) returnCallBackForObject:(id)object withData:(id)data
175         WebScriptObject *a = [callbacks objectForKey: object];
176         if (!a) {
177                 NSLog(@"Could not find a callback for object: %@", object);
178                 return;
179         }
181         [callbacks removeObjectForKey:object];
182         [a callWebScriptMethod:@"call" withArguments:[NSArray arrayWithObjects:@"", data, nil]];
185 - (void) threadFinished:(NSArray *)arguments
187         [self returnCallBackForObject:[arguments objectAtIndex:0] withData:[arguments objectAtIndex:1]];
190 - (void) JSRunCommandDone:(NSNotification *)notification
192         NSString *data = [[NSString alloc] initWithData:[[notification userInfo] valueForKey:NSFileHandleNotificationDataItem] encoding:NSUTF8StringEncoding];
193         [self returnCallBackForObject:[notification object] withData:data];
196 - (void) preferencesChanged
200 - (void)preferencesChangedWithNotification:(NSNotification *)theNotification
202         [self preferencesChanged];
205 @end