Home | History | Annotate | Download | only in mac
      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             0,
    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             0,      /* version */
    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
    267