blob: 05631d529da5f1479dae9b95ea514babb3f3ae55 [file] [log] [blame]
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "AppDelegate.h"
#import "BrowserWindowController.h"
#import "BrowserStatisticsWindowController.h"
#import <WebKit2/WKContextPrivate.h>
#import <WebKit2/WKStringCF.h>
#import <WebKit2/WKURLCF.h>
static NSString *defaultURL = @"http://www.webkit.org/";
@implementation BrowserAppDelegate
void didRecieveMessageFromInjectedBundle(WKContextRef context, WKStringRef messageName, WKTypeRef messageBody, const void *clientInfo)
{
CFStringRef cfMessageName = WKStringCopyCFString(0, messageName);
WKTypeID typeID = WKGetTypeID(messageBody);
if (typeID == WKStringGetTypeID()) {
CFStringRef cfMessageBody = WKStringCopyCFString(0, (WKStringRef)messageBody);
LOG(@"ContextInjectedBundleClient - didRecieveMessage - MessageName: %@ MessageBody %@", cfMessageName, cfMessageBody);
CFRelease(cfMessageBody);
} else {
LOG(@"ContextInjectedBundleClient - didRecieveMessage - MessageName: %@ (MessageBody Unhandeled)\n", cfMessageName);
}
CFRelease(cfMessageName);
WKStringRef newMessageName = WKStringCreateWithCFString(CFSTR("Response"));
WKStringRef newMessageBody = WKStringCreateWithCFString(CFSTR("Roger that!"));
WKContextPostMessageToInjectedBundle(context, newMessageName, newMessageBody);
WKRelease(newMessageName);
WKRelease(newMessageBody);
}
// MARK: History Client Callbacks
static void didNavigateWithNavigationData(WKContextRef context, WKPageRef page, WKNavigationDataRef navigationData, WKFrameRef frame, const void *clientInfo)
{
WKStringRef wkTitle = WKNavigationDataCopyTitle(navigationData);
CFStringRef title = WKStringCopyCFString(0, wkTitle);
WKRelease(wkTitle);
WKURLRef wkURL = WKNavigationDataCopyURL(navigationData);
CFURLRef url = WKURLCopyCFURL(0, wkURL);
WKRelease(wkURL);
LOG(@"HistoryClient - didNavigateWithNavigationData - title: %@ - url: %@", title, url);
CFRelease(title);
CFRelease(url);
}
static void didPerformClientRedirect(WKContextRef context, WKPageRef page, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void *clientInfo)
{
CFURLRef cfSourceURL = WKURLCopyCFURL(0, sourceURL);
CFURLRef cfDestinationURL = WKURLCopyCFURL(0, destinationURL);
LOG(@"HistoryClient - didPerformClientRedirect - sourceURL: %@ - destinationURL: %@", cfSourceURL, cfDestinationURL);
CFRelease(cfSourceURL);
CFRelease(cfDestinationURL);
}
static void didPerformServerRedirect(WKContextRef context, WKPageRef page, WKURLRef sourceURL, WKURLRef destinationURL, WKFrameRef frame, const void *clientInfo)
{
CFURLRef cfSourceURL = WKURLCopyCFURL(0, sourceURL);
CFURLRef cfDestinationURL = WKURLCopyCFURL(0, destinationURL);
LOG(@"HistoryClient - didPerformServerRedirect - sourceURL: %@ - destinationURL: %@", cfSourceURL, cfDestinationURL);
CFRelease(cfSourceURL);
CFRelease(cfDestinationURL);
}
static void didUpdateHistoryTitle(WKContextRef context, WKPageRef page, WKStringRef title, WKURLRef URL, WKFrameRef frame, const void *clientInfo)
{
CFStringRef cfTitle = WKStringCopyCFString(0, title);
CFURLRef cfURL = WKURLCopyCFURL(0, URL);
LOG(@"HistoryClient - didUpdateHistoryTitle - title: %@ - URL: %@", cfTitle, cfURL);
CFRelease(cfTitle);
CFRelease(cfURL);
}
static void populateVisitedLinks(WKContextRef context, const void *clientInfo)
{
LOG(@"HistoryClient - populateVisitedLinks");
}
- (id)init
{
self = [super init];
if (self) {
if ([NSEvent modifierFlags] & NSShiftKeyMask)
_currentProcessModel = kProcessModelSharedSecondaryThread;
else
_currentProcessModel = kProcessModelSharedSecondaryProcess;
WKContextHistoryClient historyClient = {
0,
self,
didNavigateWithNavigationData,
didPerformClientRedirect,
didPerformServerRedirect,
didUpdateHistoryTitle,
populateVisitedLinks
};
_threadContext = WKContextGetSharedThreadContext();
WKContextSetHistoryClient(_threadContext, &historyClient);
WKContextSetCacheModel(_threadContext, kWKCacheModelPrimaryWebBrowser);
CFStringRef bundlePathCF = (CFStringRef)[[NSBundle mainBundle] pathForAuxiliaryExecutable:@"WebBundle.bundle"];
WKStringRef bundlePath = WKStringCreateWithCFString(bundlePathCF);
_processContext = WKContextCreateWithInjectedBundlePath(bundlePath);
WKContextInjectedBundleClient bundleClient = {
0, /* version */
0, /* clientInfo */
didRecieveMessageFromInjectedBundle,
0
};
WKContextSetInjectedBundleClient(_processContext, &bundleClient);
WKContextSetHistoryClient(_processContext, &historyClient);
WKContextSetCacheModel(_processContext, kWKCacheModelPrimaryWebBrowser);
WKRelease(bundlePath);
}
return self;
}
- (IBAction)newWindow:(id)sender
{
BrowserWindowController *controller = [[BrowserWindowController alloc] initWithContext:[self getCurrentContext]];
[[controller window] makeKeyAndOrderFront:sender];
[controller loadURLString:defaultURL];
}
- (WKContextRef)getCurrentContext
{
return (_currentProcessModel == kProcessModelSharedSecondaryThread) ? _threadContext : _processContext;
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
if ([menuItem action] == @selector(setSharedProcessProcessModel:))
[menuItem setState:_currentProcessModel == kProcessModelSharedSecondaryProcess ? NSOnState : NSOffState];
else if ([menuItem action] == @selector(setSharedThreadProcessModel:))
[menuItem setState:_currentProcessModel == kProcessModelSharedSecondaryThread ? NSOnState : NSOffState];
return YES;
}
- (void)_setProcessModel:(ProcessModel)processModel
{
if (processModel == _currentProcessModel)
return;
_currentProcessModel = processModel;
}
- (IBAction)setSharedProcessProcessModel:(id)sender
{
[self _setProcessModel:kProcessModelSharedSecondaryProcess];
}
- (IBAction)setSharedThreadProcessModel:(id)sender
{
[self _setProcessModel:kProcessModelSharedSecondaryThread];
}
- (IBAction)showStatisticsWindow:(id)sender
{
static BrowserStatisticsWindowController* windowController;
if (!windowController)
windowController = [[BrowserStatisticsWindowController alloc] initWithThreadedWKContextRef:_threadContext
processWKContextRef:_processContext];
[[windowController window] makeKeyAndOrderFront:self];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self newWindow:self];
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
NSArray* windows = [NSApp windows];
for (NSWindow* window in windows) {
id delegate = [window delegate];
if ([delegate isKindOfClass:[BrowserWindowController class]]) {
BrowserWindowController *controller = (BrowserWindowController *)delegate;
[controller applicationTerminating];
}
}
WKRelease(_processContext);
_processContext = 0;
}
- (BrowserWindowController *)frontmostBrowserWindowController
{
NSArray* windows = [NSApp windows];
for (NSWindow* window in windows) {
id delegate = [window delegate];
if ([delegate isKindOfClass:[BrowserWindowController class]])
return (BrowserWindowController *)delegate;
}
return 0;
}
- (IBAction)openDocument:(id)sender
{
NSOpenPanel *openPanel = [[NSOpenPanel openPanel] retain];
[openPanel beginForDirectory:nil
file:nil
types:nil
modelessDelegate:self
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
contextInfo:0];
}
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
[sheet autorelease];
if (returnCode != NSOKButton || ![[sheet filenames] count])
return;
NSString* filePath = [[sheet filenames] objectAtIndex:0];
BrowserWindowController *controller = [self frontmostBrowserWindowController];
if (!controller) {
controller = [[BrowserWindowController alloc] initWithContext:[self getCurrentContext]];
[[controller window] makeKeyAndOrderFront:self];
}
[controller loadURLString:[[NSURL fileURLWithPath:filePath] absoluteString]];
}
@end