initial import
[vuplus_webkit] / Tools / MiniBrowser / mac / AppDelegate.m
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "AppDelegate.h"
27
28 #import "BrowserWindowController.h"
29 #import "BrowserStatisticsWindowController.h"
30
31 #import <WebKit2/WKContextPrivate.h>
32 #import <WebKit2/WKStringCF.h>
33 #import <WebKit2/WKURLCF.h>
34
35 static NSString *defaultURL = @"http://www.webkit.org/";
36
37 @implementation BrowserAppDelegate
38
39 void didRecieveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void *clientInfo)
40 {
41     CFStringRef cfMessageName = WKStringCopyCFString(0, messageName);
42
43     WKTypeID typeID = WKGetTypeID(messageBody);
44     if (typeID == WKStringGetTypeID()) {
45         CFStringRef cfMessageBody = WKStringCopyCFString(0, (WKStringRef)messageBody);
46         LOG(@"ContextInjectedBundleClient - didRecieveMessage - MessageName: %@ MessageBody %@", cfMessageName, cfMessageBody);
47         CFRelease(cfMessageBody);
48     } else {
49         LOG(@"ContextInjectedBundleClient - didRecieveMessage - MessageName: %@ (MessageBody Unhandeled)\n", cfMessageName);
50     }
51     
52     CFRelease(cfMessageName);
53
54     WKStringRef newMessageName = WKStringCreateWithCFString(CFSTR("Response"));
55     WKStringRef newMessageBody = WKStringCreateWithCFString(CFSTR("Roger that!"));
56
57     WKContextPostMessageToInjectedBundle(context, newMessageName, newMessageBody);
58     
59     WKRelease(newMessageName);
60     WKRelease(newMessageBody);
61 }
62
63 // MARK: History Client Callbacks
64
65 static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void *clientInfo)
66 {
67     WKStringRef wkTitle = WKNavigationDataCopyTitle(navigationData);
68     CFStringRef title = WKStringCopyCFString(0, wkTitle);
69     WKRelease(wkTitle);
70
71     WKURLRef wkURL = WKNavigationDataCopyURL(navigationData);
72     CFURLRef url = WKURLCopyCFURL(0, wkURL);
73     WKRelease(wkURL);
74
75     LOG(@"HistoryClient - didNavigateWithNavigationData - title: %@ - url: %@", title, url);
76     CFRelease(title);
77     CFRelease(url);
78 }
79
80 static void didPerformClientRedirect(WKContextRef context, WKPageRef page, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void *clientInfo)
81 {
82     CFURLRef cfSourceURL = WKURLCopyCFURL(0, sourceURL);
83     CFURLRef cfDestinationURL = WKURLCopyCFURL(0, destinationURL);
84     LOG(@"HistoryClient - didPerformClientRedirect - sourceURL: %@ - destinationURL: %@", cfSourceURL, cfDestinationURL);
85     CFRelease(cfSourceURL);
86     CFRelease(cfDestinationURL);
87 }
88
89 static void didPerformServerRedirect(WKContextRef context, WKPageRef page, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void *clientInfo)
90 {
91     CFURLRef cfSourceURL = WKURLCopyCFURL(0, sourceURL);
92     CFURLRef cfDestinationURL = WKURLCopyCFURL(0, destinationURL);
93     LOG(@"HistoryClient - didPerformServerRedirect - sourceURL: %@ - destinationURL: %@", cfSourceURL, cfDestinationURL);
94     CFRelease(cfSourceURL);
95     CFRelease(cfDestinationURL);
96 }
97
98 static void didUpdateHistoryTitle(WKContextRef context, WKPageRef page, WKStringRef title, WKURLRef URL, WKFrameRef frame, const void *clientInfo)
99 {
100     CFStringRef cfTitle = WKStringCopyCFString(0, title);
101     CFURLRef cfURL = WKURLCopyCFURL(0, URL);
102     LOG(@"HistoryClient - didUpdateHistoryTitle - title: %@ - URL: %@", cfTitle, cfURL);
103     CFRelease(cfTitle);
104     CFRelease(cfURL);
105 }
106
107 static void populateVisitedLinks(WKContextRef context, const void *clientInfo)
108 {
109     LOG(@"HistoryClient - populateVisitedLinks");
110 }
111
112 - (id)init
113 {
114     self = [super init];
115     if (self) {
116         if ([NSEvent modifierFlags] & NSShiftKeyMask)
117             _currentProcessModel = kProcessModelSharedSecondaryThread;
118         else
119             _currentProcessModel = kProcessModelSharedSecondaryProcess;
120
121         WKContextHistoryClient historyClient = {
122             kWKContextHistoryClientCurrentVersion,
123             self,
124             didNavigateWithNavigationData,
125             didPerformClientRedirect,
126             didPerformServerRedirect,
127             didUpdateHistoryTitle,
128             populateVisitedLinks
129         };
130
131         _threadContext = WKContextGetSharedThreadContext();
132         WKContextSetHistoryClient(_threadContext, &historyClient);
133         WKContextSetCacheModel(_threadContext, kWKCacheModelPrimaryWebBrowser);
134
135         CFStringRef bundlePathCF = (CFStringRef)[[NSBundle mainBundle] pathForAuxiliaryExecutable:@"WebBundle.bundle"];
136         WKStringRef bundlePath = WKStringCreateWithCFString(bundlePathCF);
137
138         _processContext = WKContextCreateWithInjectedBundlePath(bundlePath);
139         
140         WKContextInjectedBundleClient bundleClient = {
141             kWKContextInjectedBundleClientCurrentVersion,
142             0,      /* clientInfo */
143             didRecieveMessageFromInjectedBundle,
144             0
145         };
146         WKContextSetInjectedBundleClient(_processContext, &bundleClient);
147         WKContextSetHistoryClient(_processContext, &historyClient);
148         WKContextSetCacheModel(_processContext, kWKCacheModelPrimaryWebBrowser);
149
150         WKRelease(bundlePath);
151     }
152
153     return self;
154 }
155
156 - (IBAction)newWindow:(id)sender
157 {
158     BrowserWindowController *controller = [[BrowserWindowController alloc] initWithContext:[self getCurrentContext]];
159     [[controller window] makeKeyAndOrderFront:sender];
160     
161     [controller loadURLString:defaultURL];
162 }
163
164 - (WKContextRef)getCurrentContext
165 {
166     return (_currentProcessModel == kProcessModelSharedSecondaryThread) ? _threadContext : _processContext;
167 }
168
169 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
170 {
171     if ([menuItem action] == @selector(setSharedProcessProcessModel:))
172         [menuItem setState:_currentProcessModel == kProcessModelSharedSecondaryProcess ? NSOnState : NSOffState];
173     else if ([menuItem action] == @selector(setSharedThreadProcessModel:))
174         [menuItem setState:_currentProcessModel == kProcessModelSharedSecondaryThread ? NSOnState : NSOffState];
175     return YES;
176 }        
177
178 - (void)_setProcessModel:(ProcessModel)processModel
179 {
180     if (processModel == _currentProcessModel)
181         return;
182  
183     _currentProcessModel = processModel;
184 }
185
186 - (IBAction)setSharedProcessProcessModel:(id)sender
187 {
188     [self _setProcessModel:kProcessModelSharedSecondaryProcess];
189 }
190
191 - (IBAction)setSharedThreadProcessModel:(id)sender
192 {
193     [self _setProcessModel:kProcessModelSharedSecondaryThread];
194 }
195
196 - (IBAction)showStatisticsWindow:(id)sender
197 {
198     static BrowserStatisticsWindowController* windowController;
199     if (!windowController)
200         windowController = [[BrowserStatisticsWindowController alloc] initWithThreadedWKContextRef:_threadContext
201                                                                                processWKContextRef:_processContext];
202
203     [[windowController window] makeKeyAndOrderFront:self];
204 }
205
206 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
207 {
208     [self newWindow:self];
209 }
210
211 - (void)applicationWillTerminate:(NSNotification *)notification
212 {
213     NSArray* windows = [NSApp windows];
214     for (NSWindow* window in windows) {
215         id delegate = [window delegate];
216         if ([delegate isKindOfClass:[BrowserWindowController class]]) {
217             BrowserWindowController *controller = (BrowserWindowController *)delegate;
218             [controller applicationTerminating];
219         }
220     }
221
222     WKRelease(_processContext);
223     _processContext = 0;
224 }
225
226 - (BrowserWindowController *)frontmostBrowserWindowController
227 {
228     NSArray* windows = [NSApp windows];
229     for (NSWindow* window in windows) {
230         id delegate = [window delegate];
231         if ([delegate isKindOfClass:[BrowserWindowController class]])
232             return (BrowserWindowController *)delegate;
233     }
234
235     return 0;
236 }
237
238 - (IBAction)openDocument:(id)sender
239 {
240     NSOpenPanel *openPanel = [[NSOpenPanel openPanel] retain];
241     [openPanel beginForDirectory:nil
242         file:nil
243         types:nil
244         modelessDelegate:self
245         didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
246         contextInfo:0];
247 }
248
249 - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
250 {
251     [sheet autorelease];
252     if (returnCode != NSOKButton || ![[sheet filenames] count])
253         return;
254     
255     NSString* filePath = [[sheet filenames] objectAtIndex:0];
256
257     BrowserWindowController *controller = [self frontmostBrowserWindowController];
258     if (!controller) {
259         controller = [[BrowserWindowController alloc] initWithContext:[self getCurrentContext]];
260         [[controller window] makeKeyAndOrderFront:self];
261     }
262     
263     [controller loadURLString:[[NSURL fileURLWithPath:filePath] absoluteString]];
264 }
265
266 @end