/* * Copyright 2011 Sven Weidauer * * This file is part of NetSurf, http://www.netsurf-browser.org/ * * NetSurf is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * NetSurf is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #import "cocoa/apple_image.h" #import "cocoa/NetsurfApp.h" #import "cocoa/gui.h" #import "cocoa/plotter.h" #import "cocoa/DownloadWindowController.h" #import "cocoa/SearchWindowController.h" #import "cocoa/selection.h" #import "cocoa/fetch.h" #import "cocoa/bitmap.h" #import "cocoa/font.h" #import "utils/filename.h" #import "utils/log.h" #import "utils/messages.h" #import "utils/utils.h" #import "utils/nsoption.h" #import "utils/nsurl.h" #import "netsurf/plotters.h" #import "netsurf/mouse.h" #import "netsurf/netsurf.h" #import "netsurf/browser_window.h" #import "netsurf/cookie_db.h" #import "netsurf/url_db.h" #import "desktop/save_complete.h" #import "cocoa/desktop-tree.h" #ifndef NETSURF_HOMEPAGE #define NETSURF_HOMEPAGE "http://www.netsurf-browser.org/welcome/" #endif @implementation NetSurfApp @synthesize frontTab; static bool cocoa_done = false; /** * Cause an abnormal program termination. * * \note This never returns and is intended to terminate without any cleanup. * * \param error The message to display to the user. */ static void die(const char *const error) { [NSException raise:@"NetsurfDie" format:@"Error: %s", error]; } - (void)loadOptions { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys: cocoa_get_user_path(@"Cookies"), kCookiesFileOption, cocoa_get_user_path(@"URLs"), kURLsFileOption, [NSString stringWithUTF8String:NETSURF_HOMEPAGE], kHomepageURLOption, nil]]; nsoption_setnull_charp(cookie_file, strdup([[defaults objectForKey:kCookiesFileOption] UTF8String])); nsoption_setnull_charp(cookie_jar, strdup(nsoption_charp(cookie_file))); nsoption_setnull_charp(homepage_url, strdup([[defaults objectForKey:kHomepageURLOption] UTF8String])); urldb_load([[defaults objectForKey:kURLsFileOption] UTF8String]); urldb_load_cookies(nsoption_charp(cookie_file)); cocoa_update_scale_factor(); NSLOG(netsurf, INFO, "done setup"); } - (void)saveOptions { urldb_save_cookies(nsoption_charp(cookie_file)); urldb_save([[[NSUserDefaults standardUserDefaults] objectForKey:kURLsFileOption] UTF8String]); } - (void)run { @autoreleasepool { @autoreleasepool { [self finishLaunching]; [self loadOptions]; } while (!cocoa_done) { @autoreleasepool { NSEvent *event = [self nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES]; if (nil != event) { [self sendEvent:event]; [self updateWindows]; } } } [self saveOptions]; } } - (void)terminate:(id)sender { [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationWillTerminateNotification object:self]; cocoa_done = true; [self postEvent:[NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 context:NULL subtype:0 data1:0 data2:0] atStart:YES]; } @end #pragma mark - static NSString *cocoa_get_preferences_path(void) { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); NSCAssert([paths count] >= 1, @"Where is the application support directory?"); NSString *netsurfPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"NetSurf"]; NSFileManager *fm = [NSFileManager defaultManager]; BOOL isDirectory = NO; BOOL exists = [fm fileExistsAtPath:netsurfPath isDirectory:&isDirectory]; if (!exists) { exists = [fm createDirectoryAtPath:netsurfPath withIntermediateDirectories:YES attributes:nil error:NULL]; isDirectory = YES; } if (!(exists && isDirectory)) { die("Cannot create netsurf preferences directory"); } return netsurfPath; } NSString *cocoa_get_user_path(NSString *fileName) { return [cocoa_get_preferences_path() stringByAppendingPathComponent:fileName]; } static const char *cocoa_get_options_file(void) { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults registerDefaults:[NSDictionary dictionaryWithObjectsAndKeys: cocoa_get_user_path(@"Options"), kOptionsFileOption, nil]]; return [[defaults objectForKey:kOptionsFileOption] UTF8String]; } static NSApplication *cocoa_prepare_app(void) { /* if application instance has already been created return it */ if (NSApp != nil) { return NSApp; } NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary]; /* Obtain principle class of bundle which must implement sharedApplication API */ Class principalClass = NSClassFromString([infoDictionary objectForKey:@"NSPrincipalClass"]); NSCAssert([principalClass respondsToSelector:@selector(sharedApplication)], @"Principal class must implement sharedApplication."); /* create application instance */ [principalClass sharedApplication]; /* load interface nib */ NSString *mainNibName = [infoDictionary objectForKey:@"NSMainNibFile"]; NSNib *mainNib = [[NSNib alloc] initWithNibNamed:mainNibName bundle:[NSBundle mainBundle]]; [mainNib instantiateNibWithOwner:NSApp topLevelObjects:nil]; return NSApp; } /** * Set option defaults for cocoa frontend * * @param defaults The option table to update. * @return error status. */ static nserror set_defaults(struct nsoption_s *defaults) { /* Set defaults for absent option strings */ const char *const ca_bundle = [[[NSBundle mainBundle] pathForResource:@"ca-bundle" ofType:@""] UTF8String]; nsoption_setnull_charp(ca_bundle, strdup(ca_bundle)); return NSERROR_OK; } int main(int argc, char **argv) { nsurl *url; nserror error; struct netsurf_table cocoa_table = { .misc = cocoa_misc_table, .window = cocoa_window_table, .clipboard = cocoa_clipboard_table, .download = cocoa_download_table, .fetch = cocoa_fetch_table, .search = cocoa_search_table, .bitmap = cocoa_bitmap_table, .layout = cocoa_layout_table, }; error = netsurf_register(&cocoa_table); if (error != NSERROR_OK) { die("NetSurf operation table failed registration"); } const char *const messages = [[[NSBundle mainBundle] pathForResource:@"Messages" ofType:@""] UTF8String]; const char *const options = cocoa_get_options_file(); /* initialise logging. Not fatal if it fails but not much we * can do about it either. */ nslog_init(NULL, &argc, argv); /* user options setup */ error = nsoption_init(set_defaults, &nsoptions, &nsoptions_default); if (error != NSERROR_OK) { die("Options failed to initialise"); } nsoption_read(options, NULL); nsoption_commandline(&argc, argv, NULL); error = messages_add_from_file(messages); /* common initialisation */ error = netsurf_init(NULL); if (error != NSERROR_OK) { die("NetSurf failed to initialise"); } /* Initialise filename allocator */ filename_initialise(); (void)apple_image_init(); NSApplication *app = cocoa_prepare_app(); for (int i = 1; i < argc; i++) { /* skip -psn_* and other possible options */ if (argv[i][0] == '-') continue; error = nsurl_create(argv[i], &url); if (error == NSERROR_OK) { error = browser_window_create(BW_CREATE_HISTORY, url, NULL, NULL, NULL); nsurl_unref(url); } if (error != NSERROR_OK) { cocoa_warning(messages_get_errorcode(error), 0); } } [app run]; netsurf_exit(); return 0; }