diff --git a/camino/src/application/MainController.h b/camino/src/application/MainController.h index 837a3bc47cb9..7d8e562cf333 100644 --- a/camino/src/application/MainController.h +++ b/camino/src/application/MainController.h @@ -62,11 +62,11 @@ typedef enum EBookmarkOpenBehavior @interface MainController : NSObject { IBOutlet NSApplication* mApplication; - + // The following item is added to NSSavePanels as an accessory view IBOutlet NSView* mFilterView; IBOutlet NSView* mExportPanelView; - + // IBOutlet NSMenuItem* mOfflineMenuItem; IBOutlet NSMenuItem* mCloseWindowMenuItem; IBOutlet NSMenuItem* mCloseTabMenuItem; @@ -88,7 +88,7 @@ typedef enum EBookmarkOpenBehavior IBOutlet NSMenuItem* mCreateBookmarksFolderMenuItem; IBOutlet NSMenuItem* mCreateBookmarksSeparatorMenuItem; // unused IBOutlet NSMenuItem* mShowAllBookmarksMenuItem; - + BOOL mOffline; BOOL mGeckoInitted; BOOL mBookmarksMenuUpdatePending; @@ -97,122 +97,112 @@ typedef enum EBookmarkOpenBehavior BookmarkMenu* mMenuBookmarks; BookmarkMenu* mDockBookmarks; - + KeychainService* mKeychainService; FindDlgController* mFindDialog; NSString* mStartURL; - + SharedMenusObj* mSharedMenusObj; NSMutableDictionary* mCharsets; } --(IBAction)aboutWindow:(id)sender; --(IBAction) feedbackLink:(id)aSender; +// Application menu actions +- (IBAction)aboutWindow:(id)sender; +- (IBAction)feedbackLink:(id)aSender; +- (IBAction)displayPreferencesWindow:(id)sender; +- (IBAction)resetBrowser:(id)sender; +- (IBAction)emptyCache:(id)sender; -// File menu actions. --(IBAction) newWindow:(id)aSender; --(IBAction) newTab:(id)aSender; --(IBAction) closeAllWindows:(id)aSender; --(IBAction) closeTab:(id)aSender; --(IBAction) openFile:(id)aSender; --(IBAction) openLocation:(id)aSender; --(IBAction) savePage:(id)aSender; --(IBAction) pageSetup:(id)aSender; --(IBAction) printPage:(id)aSender; --(IBAction) toggleOfflineMode:(id)aSender; --(IBAction) sendURL:(id)aSender; +// File menu actions +- (IBAction)newWindow:(id)aSender; +- (IBAction)newTab:(id)aSender; +- (IBAction)openFile:(id)aSender; +- (IBAction)openLocation:(id)aSender; +- (IBAction)doSearch:(id)aSender; +- (IBAction)closeAllWindows:(id)aSender; +- (IBAction)closeTab:(id)aSender; +- (IBAction)savePage:(id)aSender; +- (IBAction)sendURL:(id)aSender; +- (IBAction)importBookmarks:(id)aSender; +- (IBAction)exportBookmarks:(id)aSender; +- (IBAction)pageSetup:(id)aSender; +- (IBAction)printPage:(id)aSender; +- (IBAction)toggleOfflineMode:(id)aSender; // unused -// Edit menu actions. --(IBAction) findInPage:(id)aSender; - -// Go menu actions. --(IBAction) goBack:(id)aSender; --(IBAction) goForward:(id)aSender; --(IBAction) goHome:(id)aSender; --(IBAction) doSearch:(id)aSender; - -// Local servers submenu --(IBAction) aboutServers:(id)aSender; --(IBAction) connectToServer:(id)aSender; +// Edit menu actions +- (IBAction)findInPage:(id)aSender; // View menu actions. --(IBAction) toggleBookmarksToolbar:(id)aSender; --(IBAction) doReload:(id)aSender; --(IBAction) doReloadAllTabs:(id)aSender; --(IBAction) doStop:(id)aSender; --(IBAction) makeTextBigger:(id)aSender; --(IBAction) makeTextSmaller:(id)aSender; --(IBAction) makeTextDefaultSize:(id)aSender; --(IBAction) viewSource:(id)aSender; --(IBAction) manageBookmarks: (id)aSender; --(IBAction) showHistory:(id)aSender; --(IBAction) clearHistory:(id)aSender; --(IBAction) reloadWithCharset:(id)aSender; --(IBAction) toggleAutoCharsetDetection:(id)aSender; +- (IBAction)toggleBookmarksToolbar:(id)aSender; +- (IBAction)doStop:(id)aSender; +- (IBAction)doReload:(id)aSender; +- (IBAction)doReloadAllTabs:(id)aSender; +- (IBAction)makeTextBigger:(id)aSender; +- (IBAction)makeTextDefaultSize:(id)aSender; +- (IBAction)makeTextSmaller:(id)aSender; +- (IBAction)viewSource:(id)aSender; +- (IBAction)reloadWithCharset:(id)aSender; +- (IBAction)toggleAutoCharsetDetection:(id)aSender; -// Bookmarks menu actions. --(IBAction) importBookmarks:(id)aSender; --(IBAction) exportBookmarks:(id)aSender; +// History menu actions +- (IBAction)goHome:(id)aSender; +- (IBAction)goBack:(id)aSender; +- (IBAction)goForward:(id)aSender; +- (IBAction)showHistory:(id)aSender; +- (IBAction)clearHistory:(id)aSender; --(IBAction) openMenuBookmark:(id)aSender; +// Bookmarks menu actions +- (IBAction)manageBookmarks: (id)aSender; +- (IBAction)openMenuBookmark:(id)aSender; + +// Bonjour submenu +- (IBAction)aboutServers:(id)aSender; +- (IBAction)connectToServer:(id)aSender; // Window menu actions --(IBAction) zoomAll:(id)aSender; --(IBAction) previousTab:(id)aSender; --(IBAction) nextTab:(id)aSender; --(IBAction) downloadsWindow:(id)aSender; +- (IBAction)zoomAll:(id)aSender; +- (IBAction)previousTab:(id)aSender; +- (IBAction)nextTab:(id)aSender; +- (IBAction)downloadsWindow:(id)aSender; // Help menu actions --(IBAction) supportLink:(id)aSender; --(IBAction) infoLink:(id)aSender; --(IBAction) releaseNoteLink:(id)aSender; --(IBAction) tipsTricksLink:(id)aSender; --(IBAction) searchCustomizeLink:(id)aSender; +- (IBAction)supportLink:(id)aSender; +- (IBAction)infoLink:(id)aSender; +- (IBAction)aboutPlugins:(id)aSender; +- (IBAction)releaseNoteLink:(id)aSender; // unused +- (IBAction)tipsTricksLink:(id)aSender; // unused +- (IBAction)searchCustomizeLink:(id)aSender; // unused --(IBAction) aboutPlugins:(id)aSender; - --(IBAction) showCertificates:(id)aSender; +// used by export bookmarks popup to set file extension for the resulting bookmarks file +- (IBAction)setFileExtension:(id)aSender; +// used by page info panel to show certificate information +- (IBAction)showCertificates:(id)aSender; - (void)ensureGeckoInitted; +// if the main/key window is a browser window, return its controller, otherwise nil +- (BrowserWindowController*)getMainWindowBrowserController; +- (BrowserWindowController*)getKeyWindowBrowserController; +- (NSWindow*)getFrontmostBrowserWindow; +- (BOOL)isMainWindowABrowserWindow; + - (BrowserWindowController*)openBrowserWindowWithURL:(NSString*)aURL andReferrer:(NSString*)aReferrer behind:(NSWindow*)window allowPopups:(BOOL)inAllowPopups; - (BrowserWindowController*)openBrowserWindowWithURLs:(NSArray*)urlArray behind:(NSWindow*)window allowPopups:(BOOL)inAllowPopups; - - (void)openNewWindowOrTabWithURL:(NSString*)inURLString andReferrer:(NSString*)aReferrer alwaysInFront:(BOOL)forceFront; +- (void)loadBookmark:(BookmarkItem*)item withBWC:(BrowserWindowController*)browserWindowController openBehavior:(EBookmarkOpenBehavior)behavior reverseBgToggle:(BOOL)reverseBackgroundPref; - (void)adjustCloseWindowMenuItemKeyEquivalent:(BOOL)inHaveTabs; - (void)adjustCloseTabMenuItemKeyEquivalent:(BOOL)inHaveTabs; - (void)delayedFixCloseMenuItemKeyEquivalents; - - (void)delayedAdjustBookmarksMenuItemsEnabling; - (void)delayedUpdatePageInfo; - (NSView*)getSavePanelView; -- (NSWindow*)getFrontmostBrowserWindow; - -- (void)loadBookmark:(BookmarkItem*)item withBWC:(BrowserWindowController*)browserWindowController openBehavior:(EBookmarkOpenBehavior)behavior reverseBgToggle:(BOOL)reverseBackgroundPref; -- (void)displayPreferencesWindow:(id)sender; -- (BOOL)isMainWindowABrowserWindow; - -// if the main window is a browser window, return its controller, otherwise nil -- (BrowserWindowController*)getMainWindowBrowserController; -- (BrowserWindowController*)getKeyWindowBrowserController; + (NSImage*)createImageForDragging:(NSImage*)aIcon title:(NSString*)aTitle; - -// used by export bookmarks popup to say what file extension should be used on the resulting -// bookmarks file. --(IBAction) setFileExtension:(id)aSender; - // utility routine to test if a url is "blank" (either empty or about:blank) -+(BOOL)isBlankURL:(NSString*)inURL; - -// security feature to reset browser --(IBAction)resetBrowser:(id)sender; - -// prompts the user to reset the cache, then does it -- (IBAction)emptyCache:(id)sender; ++ (BOOL)isBlankURL:(NSString*)inURL; @end diff --git a/camino/src/application/MainController.mm b/camino/src/application/MainController.mm index 6fadf4906b69..f3417d291eca 100644 --- a/camino/src/application/MainController.mm +++ b/camino/src/application/MainController.mm @@ -91,7 +91,7 @@ #include "nsIBrowserHistory.h" #include "nsICacheService.h" -extern const nsModuleComponentInfo* GetAppComponents(unsigned int * outNumComponents); +extern const nsModuleComponentInfo* GetAppComponents(unsigned int* outNumComponents); static const char* ioServiceContractID = "@mozilla.org/network/io-service;1"; @@ -106,21 +106,19 @@ const int kReuseWindowOnAE = 2; - (void)setupStartpage; - (void)setupRendezvous; - (void)checkDefaultBrowser; -- (NSMenu*)bookmarksMenu; - (BOOL)bookmarksItemsEnabled; - (void)adjustBookmarkMenuItems; - (void)updateDockMenuBookmarkFolder; - (void)doBookmarksMenuEnabling; - (void)adjustTextEncodingMenu; - - (void)windowLayeringDidChange:(NSNotification*)inNotification; - (void)bookmarkLoadingCompleted:(NSNotification*)inNotification; - (void)dockMenuBookmarkFolderChanged:(NSNotification*)inNotification; - (void)menuWillDisplay:(NSNotification*)inNotification; - (void)showCertificatesNotification:(NSNotification*)inNotification; - (void)openPanelDidEnd:(NSOpenPanel*)inOpenPanel returnCode:(int)inReturnCode contextInfo:(void*)inContextInfo; - --(NSArray*)browserWindows; +- (NSArray*)browserWindows; ++ (NSURL*)decodeLocalFileURL:(NSURL*)url; @end @@ -128,32 +126,32 @@ const int kReuseWindowOnAE = 2; @implementation MainController --(id)init +- (id)init { - if ( (self = [super init]) ) { + if ((self = [super init])) { //XXX An updated version of this will be needed again once we're 10.4+ (See Bug 336217) -#if 0 +#if 0 // ensure that we're at least on 10.2 as lower OS versions are not supported any more long version = 0; ::Gestalt(gestaltSystemVersion, &version); if (version < 0x00001020) { NSString* appName = NSLocalizedStringFromTable(@"CFBundleName", @"InfoPlist", nil); - NSString* alert = [NSString stringWithFormat: NSLocalizedString(@"RequiredVersionNotMetTitle", @""), appName]; - NSString* message = [NSString stringWithFormat: NSLocalizedString(@"RequiredVersionNotMet", @""), appName]; + NSString* alert = [NSString stringWithFormat:NSLocalizedString(@"RequiredVersionNotMetTitle", @""), appName]; + NSString* message = [NSString stringWithFormat:NSLocalizedString(@"RequiredVersionNotMet", @""), appName]; NSString* quit = NSLocalizedString(@"QuitButtonText",@""); NSRunAlertPanel(alert, message, quit, nil, nil); [NSApp terminate:self]; } #endif - + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; NSString* url = [defaults stringForKey:USER_DEFAULTS_URL_KEY]; mStartURL = url ? [url retain] : nil; - + mFindDialog = nil; mMenuBookmarks = nil; - + [NSApp setServicesProvider:self]; // Initialize shared menu support mSharedMenusObj = [[SharedMenusObj alloc] init]; @@ -161,16 +159,16 @@ const int kReuseWindowOnAE = 2; return self; } --(void)dealloc +- (void)dealloc { [mCharsets release]; - + // Terminate shared menus [mSharedMenusObj release]; [mFindDialog release]; [mKeychainService release]; - + [super dealloc]; #if DEBUG NSLog(@"Main controller died"); @@ -203,23 +201,23 @@ const int kReuseWindowOnAE = 2; mGeckoInitted = YES; } --(void)applicationDidFinishLaunching:(NSNotification *)aNotification +- (void)applicationDidFinishLaunching:(NSNotification*)aNotification { [self ensureGeckoInitted]; NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter]; // turn on menu display notifications [NSMenu setupMenuWillDisplayNotifications]; - + // register for them for bookmarks [notificationCenter addObserver:self selector:@selector(menuWillDisplay:) name:NSMenuWillDisplayNotification object:nil]; - + // register for various window layering changes [notificationCenter addObserver:self selector:@selector(windowLayeringDidChange:) name:NSWindowDidBecomeKeyNotification object:nil]; [notificationCenter addObserver:self selector:@selector(windowLayeringDidChange:) name:NSWindowDidResignKeyNotification object:nil]; [notificationCenter addObserver:self selector:@selector(windowLayeringDidChange:) name:NSWindowDidBecomeMainNotification object:nil]; [notificationCenter addObserver:self selector:@selector(windowLayeringDidChange:) name:NSWindowDidResignMainNotification object:nil]; - + // listen for bookmark loading completion [notificationCenter addObserver:self selector:@selector(bookmarkLoadingCompleted:) name:kBookmarkManagerStartedNotification object:nil]; // listen for changes to the dock menu @@ -236,7 +234,7 @@ const int kReuseWindowOnAE = 2; // listen for the Show Certificates notification (which is send from the Security prefs panel) [notificationCenter addObserver:self selector:@selector(showCertificatesNotification:) name:@"ShowCertificatesNotification" object:nil]; - + [self setupStartpage]; // Initialize offline mode. @@ -247,17 +245,17 @@ const int kReuseWindowOnAE = 2; PRBool offline = PR_FALSE; ioService->GetOffline(&offline); mOffline = offline; - + // Initialize the keychain service. mKeychainService = [KeychainService instance]; - + // bring up the JS console service BOOL success; if ([[PreferenceManager sharedInstance] getBooleanPref:"chimera.log_js_to_console" withSuccess:&success]) [JSConsole sharedJSConsole]; [self setupRendezvous]; - + // load up the charset dictionary with keys and menu titles. NSString* charsetPath = [NSBundle pathForResource:@"Charset" ofType:@"dict" inDirectory:[[NSBundle mainBundle] bundlePath]]; mCharsets = [[NSDictionary dictionaryWithContentsOfFile:charsetPath] retain]; @@ -272,18 +270,18 @@ const int kReuseWindowOnAE = 2; [self performSelector:@selector(checkDefaultBrowser) withObject:nil afterDelay:2.0f]; } -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender +- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication*)sender { ProgressDlgController* progressWindowController = [ProgressDlgController existingSharedDownloadController]; - if (progressWindowController) - { + if (progressWindowController) { NSApplicationTerminateReply progressTerminateReply = [progressWindowController allowTerminate]; if (progressTerminateReply != NSTerminateNow) return progressTerminateReply; } PreferenceManager* prefManager = [PreferenceManager sharedInstanceDontCreate]; - if (!prefManager) return NSTerminateNow; // we didn't fully launch + if (!prefManager) + return NSTerminateNow; // we didn't fully launch if (![prefManager getBooleanPref:"camino.warn_when_closing" withSuccess:NULL]) return NSTerminateNow; @@ -292,29 +290,25 @@ const int kReuseWindowOnAE = 2; NSString* quitAlertExpl = nil; NSArray* openBrowserWins = [self browserWindows]; - if ([openBrowserWins count] == 1) - { + if ([openBrowserWins count] == 1) { BrowserWindowController* bwc = [[openBrowserWins firstObject] windowController]; unsigned int numTabs = [[bwc getTabBrowser] numberOfTabViewItems]; - if (numTabs > 1) - { + if (numTabs > 1) { quitAlertMsg = NSLocalizedString(@"QuitWithMultipleTabsMsg", @""); quitAlertExpl = [NSString stringWithFormat:NSLocalizedString(@"QuitWithMultipleTabsExpl", @""), numTabs]; } } - else if ([openBrowserWins count] > 1) - { + else if ([openBrowserWins count] > 1) { quitAlertMsg = NSLocalizedString(@"QuitWithMultipleWindowsMsg", @""); quitAlertExpl = [NSString stringWithFormat:NSLocalizedString(@"QuitWithMultipleWindowsExpl", @""), [openBrowserWins count]]; } - if (quitAlertMsg) - { + if (quitAlertMsg) { [NSApp activateIgnoringOtherApps:YES]; nsAlertController* controller = CHBrowserService::GetAlertController(); BOOL dontShowAgain = NO; BOOL confirmed = NO; - + NS_DURING confirmed = [controller confirmCheckEx:nil title:quitAlertMsg @@ -330,18 +324,18 @@ const int kReuseWindowOnAE = 2; if (dontShowAgain) [prefManager setPref:"camino.warn_when_closing" toBoolean:NO]; - return (confirmed) ? NSTerminateNow : NSTerminateCancel; + return confirmed ? NSTerminateNow : NSTerminateCancel; } - + return NSTerminateNow; } --(void)applicationWillTerminate: (NSNotification*)aNotification +- (void)applicationWillTerminate:(NSNotification*)aNotification { #if DEBUG NSLog(@"App will terminate notification"); #endif - + [NetworkServices shutdownNetworkServices]; // make sure the info window is closed @@ -349,7 +343,7 @@ const int kReuseWindowOnAE = 2; // shut down bookmarks (if we made them) [[BookmarkManager sharedBookmarkManagerDontCreate] shutdown]; - + // Save or remove the download list according to the users download removal pref ProgressDlgController* progressWindowController = [ProgressDlgController existingSharedDownloadController]; if (progressWindowController) @@ -359,41 +353,24 @@ const int kReuseWindowOnAE = 2; NSWindow* curMainWindow = [mApplication mainWindow]; if (curMainWindow && [[curMainWindow windowController] respondsToSelector:@selector(autosaveWindowFrame)]) [[curMainWindow windowController] autosaveWindowFrame]; - + // Cancel outstanding site icon loads [[RemoteDataProvider sharedRemoteDataProvider] cancelOutstandingRequests]; - + // Release before calling TermEmbedding since we need to access XPCOM // to save preferences [MVPreferencesController clearSharedInstance]; - + CHBrowserService::TermEmbedding(); - + [self autorelease]; } -- (void)windowLayeringDidChange:(NSNotification*)inNotification -{ - [self delayedAdjustBookmarksMenuItemsEnabling]; - [self delayedFixCloseMenuItemKeyEquivalents]; - [self delayedUpdatePageInfo]; -} - -- (NSMenu *)applicationDockMenu:(NSApplication *)sender -{ - // The OS check is needed because 10.3 can't handle alternates in dock menus. Remove it (and the |withAlternates| params - // that exist to deal with it) once we're 10.4+ - BOOL isTigerOrHigher = [NSWorkspace isTigerOrHigher]; - - // the dock menu doesn't get the usual show notifications, so we rebuild it explicitly here - [mDockMenu rebuildMenuIncludingSubmenus:YES withAlternates:isTigerOrHigher]; - return mDockMenu; -} - - (void)setupStartpage { // only do this if no url was specified in the command-line - if (mStartURL) return; + if (mStartURL) + return; // for non-nightly builds, show a special start page PreferenceManager* prefManager = [PreferenceManager sharedInstance]; NSString* vendorSubString = [prefManager getStringPref:"general.useragent.vendorSub" withSuccess:NULL]; @@ -401,7 +378,7 @@ const int kReuseWindowOnAE = 2; // has the user seen this already? NSString* startPageRev = [prefManager getStringPref:"browser.startup_page_override.version" withSuccess:NULL]; if (![vendorSubString isEqualToString:startPageRev]) { - NSString* startPage = NSLocalizedStringFromTable( @"StartPageDefault", @"WebsiteDefaults", nil); + NSString* startPage = NSLocalizedStringFromTable(@"StartPageDefault", @"WebsiteDefaults", nil); if ([startPage length] && ![startPage isEqualToString:@"StartPageDefault"]) { [mStartURL release]; mStartURL = [startPage retain]; @@ -438,21 +415,18 @@ const int kReuseWindowOnAE = 2; NSString* myIdentifier = [[NSBundle mainBundle] bundleIdentifier]; // silently update from our old to new bundle identifier - if ([defaultBrowserIdentifier isEqualToString:@"org.mozilla.navigator"]) - { + if ([defaultBrowserIdentifier isEqualToString:@"org.mozilla.navigator"]) { [[NSWorkspace sharedWorkspace] setDefaultBrowserWithIdentifier:myIdentifier]; } - else if (![defaultBrowserIdentifier isEqualToString:myIdentifier]) - { + else if (![defaultBrowserIdentifier isEqualToString:myIdentifier]) { BOOL gotPref; BOOL allowPrompt = ([[PreferenceManager sharedInstance] getBooleanPref:"camino.check_default_browser" withSuccess:&gotPref] || !gotPref); - if (allowPrompt) - { + if (allowPrompt) { nsAlertController* controller = [[nsAlertController alloc] init]; BOOL dontAskAgain = NO; int result = NSAlertErrorReturn; - + NS_DURING result = [controller confirmCheckEx:nil // parent title:NSLocalizedString(@"DefaultBrowserTitle", nil) @@ -463,15 +437,13 @@ const int kReuseWindowOnAE = 2; checkMsg:NSLocalizedString(@"DefaultBrowserChecboxTitle", nil) checkValue:&dontAskAgain]; NS_HANDLER - NS_ENDHANDLER - - if (result == NSAlertDefaultReturn) - { - [[NSWorkspace sharedWorkspace] setDefaultBrowserWithIdentifier:myIdentifier]; - } - - [[PreferenceManager sharedInstance] setPref:"camino.check_default_browser" toBoolean:!dontAskAgain]; - [controller release]; + NS_ENDHANDLER + + if (result == NSAlertDefaultReturn) + [[NSWorkspace sharedWorkspace] setDefaultBrowserWithIdentifier:myIdentifier]; + + [[PreferenceManager sharedInstance] setPref:"camino.check_default_browser" toBoolean:!dontAskAgain]; + [controller release]; } } } @@ -488,14 +460,175 @@ const int kReuseWindowOnAE = 2; [self updateDockMenuBookmarkFolder]; } -- (void)dockMenuBookmarkFolderChanged:(NSNotification*)inNotification +#pragma mark - +#pragma mark Window Accesssors + +- (NSArray*)browserWindows { - [self updateDockMenuBookmarkFolder]; + NSEnumerator* windowEnum = [[NSApp orderedWindows] objectEnumerator]; + NSMutableArray* windowArray = [NSMutableArray array]; + + NSWindow* curWindow; + while ((curWindow = [windowEnum nextObject])) { + // not all browser windows are created equal. We only consider those with + // an empty chrome mask, or ones with a toolbar, status bar, and resize control + // to be real top-level browser windows for purposes of saving size and + // loading urls in. Others are popups and are transient. + if (([curWindow isVisible] || [curWindow isMiniaturized] || [NSApp isHidden]) && + [[curWindow windowController] isMemberOfClass:[BrowserWindowController class]] && + [[curWindow windowController] hasFullBrowserChrome]) + { + [windowArray addObject:curWindow]; + } + } + + return windowArray; } -- (void)updateDockMenuBookmarkFolder +- (NSWindow*)getFrontmostBrowserWindow { - [mDockMenu setBookmarkFolder:[[BookmarkManager sharedBookmarkManager] dockMenuFolder]]; + // for some reason, [NSApp mainWindow] doesn't always work, so we have to + // do this manually + NSEnumerator* windowEnum = [[NSApp orderedWindows] objectEnumerator]; + NSWindow* foundWindow = nil; + + NSWindow* curWindow; + while ((curWindow = [windowEnum nextObject])) { + // not all browser windows are created equal. We only consider those with + // an empty chrome mask, or ones with a toolbar, status bar, and resize control + // to be real top-level browser windows for purposes of saving size and + // loading urls in. Others are popups and are transient. + if (([curWindow isVisible] || [curWindow isMiniaturized] || [NSApp isHidden]) && + [[curWindow windowController] isMemberOfClass:[BrowserWindowController class]] && + [[curWindow windowController] hasFullBrowserChrome]) + { + foundWindow = curWindow; + break; + } + } + + return foundWindow; +} + +- (BrowserWindowController*)getMainWindowBrowserController +{ + // note that [NSApp mainWindow] will return NULL if we are not frontmost + NSWindowController* mainWindowController = [[mApplication mainWindow] windowController]; + if (mainWindowController && [mainWindowController isMemberOfClass:[BrowserWindowController class]]) + return (BrowserWindowController*)mainWindowController; + + return nil; +} + +- (BrowserWindowController*)getKeyWindowBrowserController +{ + NSWindowController* keyWindowController = [[mApplication keyWindow] windowController]; + if (keyWindowController && [keyWindowController isMemberOfClass:[BrowserWindowController class]]) + return (BrowserWindowController*)keyWindowController; + + return nil; +} + +- (BOOL)isMainWindowABrowserWindow +{ + // see also getFrontmostBrowserWindow. That will always return a browser + // window if one exists. This will only return one if it is frontmost. + return [[[mApplication mainWindow] windowController] isMemberOfClass:[BrowserWindowController class]]; +} + +#pragma mark - +#pragma mark Page Loading + +- (BrowserWindowController*)openBrowserWindowWithURL:(NSString*)aURL andReferrer:(NSString*)aReferrer behind:(NSWindow*)window allowPopups:(BOOL)inAllowPopups +{ + BrowserWindowController* browser = [[BrowserWindowController alloc] initWithWindowNibName:@"BrowserWindow"]; + + if (window) { + BrowserWindow* browserWin = (BrowserWindow*)[browser window]; + [browserWin setSuppressMakeKeyFront:YES]; // prevent gecko focus bringing the window to the front + [browserWin orderWindow:NSWindowBelow relativeTo:[window windowNumber]]; + [browserWin setSuppressMakeKeyFront:NO]; + } + else { + [browser showWindow:self]; + } + + // The process of creating a new tab in this brand new window loads about:blank for us as a + // side effect of calling GetDocument(). We don't need to do it again. + if ([MainController isBlankURL:aURL]) + [browser disableLoadPage]; + else + [browser loadURL:aURL referrer:aReferrer focusContent:YES allowPopups:inAllowPopups]; + + return browser; +} + +- (BrowserWindowController*)openBrowserWindowWithURLs:(NSArray*)urlArray behind:(NSWindow*)window allowPopups:(BOOL)inAllowPopups +{ + BrowserWindowController* browser = [[BrowserWindowController alloc] initWithWindowNibName:@"BrowserWindow"]; + + if (window) { + BrowserWindow* browserWin = (BrowserWindow*)[browser window]; + [browserWin setSuppressMakeKeyFront:YES]; // prevent gecko focus bringing the window to the front + [browserWin orderWindow:NSWindowBelow relativeTo:[window windowNumber]]; + [browserWin setSuppressMakeKeyFront:NO]; + } + else { + [browser showWindow:self]; + } + + [browser openURLArray:urlArray tabOpenPolicy:eReplaceTabs allowPopups:inAllowPopups]; + return browser; +} + +// open a new URL, observing the prefs on how to behave +- (void)openNewWindowOrTabWithURL:(NSString*)inURLString andReferrer:(NSString*)aReferrer alwaysInFront:(BOOL)forceFront +{ + // make sure we're initted + [PreferenceManager sharedInstance]; + + PRInt32 reuseWindow = 0; + PRBool loadInBackground = PR_FALSE; + + nsCOMPtr prefService(do_GetService(NS_PREF_CONTRACTID)); + if (prefService) { + prefService->GetIntPref("browser.reuse_window", &reuseWindow); + if (!forceFront) + prefService->GetBoolPref("browser.tabs.loadInBackground", &loadInBackground); + } + + // reuse the main window (if there is one) based on the pref in the + // tabbed browsing panel. The user may have closed all of + // them or we may get this event at startup before we've had time to load + // our window. + BrowserWindowController* controller = (BrowserWindowController*)[[self getFrontmostBrowserWindow] windowController]; + if (controller) { + BOOL tabOrWindowIsAvailable = ([[controller getBrowserWrapper] isEmpty] && ![[controller getBrowserWrapper] isBusy]); + + if (tabOrWindowIsAvailable || reuseWindow == kReuseWindowOnAE) + [controller loadURL:inURLString]; + else if (reuseWindow == kOpenNewTabOnAE) + [controller openNewTabWithURL:inURLString referrer:aReferrer loadInBackground:loadInBackground allowPopups:NO setJumpback:NO]; + else { + // note that we're opening a new window here + controller = [controller openNewWindowWithURL:inURLString referrer:aReferrer loadInBackground:loadInBackground allowPopups:NO]; + } + if (!loadInBackground) + [[controller window] makeKeyAndOrderFront:nil]; + } + else + controller = [self openBrowserWindowWithURL:inURLString andReferrer:aReferrer behind:nil allowPopups:NO]; +} + +- (BOOL)application:(NSApplication*)theApplication openFile:(NSString*)filename +{ + // We can get called before -applicationDidFinishLaunching, so make sure gecko + // has been initted + [self ensureGeckoInitted]; + + NSURL* urlToOpen = [MainController decodeLocalFileURL:[NSURL fileURLWithPath:filename]]; + [self openNewWindowOrTabWithURL:[urlToOpen absoluteString] andReferrer:nil alwaysInFront:YES]; + return YES; } // a central place for bookmark opening logic @@ -506,7 +639,7 @@ const int kReuseWindowOnAE = 2; { if (!browserWindowController) browserWindowController = [self getMainWindowBrowserController]; - + BOOL openInNewWindow = (browserWindowController == nil); BOOL openInNewTab = NO; BOOL newTabInBackground = NO; @@ -520,13 +653,13 @@ const int kReuseWindowOnAE = 2; NSWindow* behindWindow = nil; // eBookmarkOpenBehavior_Preferred not specified, since it uses all the default behaviors - switch (behavior) - { + switch (behavior) { case eBookmarkOpenBehavior_NewPreferred: if ([[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.opentabfor.middleclick" withSuccess:NULL]) { openInNewTab = YES; newTabInBackground = loadNewTabsInBackgroundPref; - } else { + } + else { openInNewWindow = YES; if (loadNewTabsInBackgroundPref) behindWindow = [browserWindowController window]; @@ -548,58 +681,226 @@ const int kReuseWindowOnAE = 2; openInNewWindow = YES; if (loadNewTabsInBackgroundPref) behindWindow = [browserWindowController window]; - break; + break; } // we allow popups for the load that fires off a bookmark. Subsequent page loads, however, will // not allow popups (if blocked). if ([item isKindOfClass:[Bookmark class]]) { if (openInNewWindow) - [self openBrowserWindowWithURL:[(Bookmark *)item url] andReferrer:nil behind:behindWindow allowPopups:YES]; + [self openBrowserWindowWithURL:[(Bookmark*)item url] andReferrer:nil behind:behindWindow allowPopups:YES]; else if (openInNewTab) - [browserWindowController openNewTabWithURL:[(Bookmark *)item url] referrer:nil loadInBackground:newTabInBackground allowPopups:YES setJumpback:NO]; + [browserWindowController openNewTabWithURL:[(Bookmark*)item url] referrer:nil loadInBackground:newTabInBackground allowPopups:YES setJumpback:NO]; else - [browserWindowController loadURL:[(Bookmark *)item url] referrer:nil focusContent:YES allowPopups:YES]; + [browserWindowController loadURL:[(Bookmark*)item url] referrer:nil focusContent:YES allowPopups:YES]; } else if ([item isKindOfClass:[BookmarkFolder class]]) { if (openInNewWindow) - [self openBrowserWindowWithURLs:[(BookmarkFolder *)item childURLs] behind:behindWindow allowPopups:YES]; + [self openBrowserWindowWithURLs:[(BookmarkFolder*)item childURLs] behind:behindWindow allowPopups:YES]; else if (openInNewTab) - [browserWindowController openURLArray:[(BookmarkFolder *)item childURLs] tabOpenPolicy:eAppendTabs allowPopups:YES]; + [browserWindowController openURLArray:[(BookmarkFolder*)item childURLs] tabOpenPolicy:eAppendTabs allowPopups:YES]; else - [browserWindowController openURLArrayReplacingTabs:[(BookmarkFolder *)item childURLs] closeExtraTabs:[(BookmarkFolder *)item isGroup] allowPopups:YES]; + [browserWindowController openURLArrayReplacingTabs:[(BookmarkFolder*)item childURLs] closeExtraTabs:[(BookmarkFolder*)item isGroup] allowPopups:YES]; } } -/* -This takes an NSURL to a local file, and if that file is a file that contains -a URL we want and isn't the content itself, we return the URL it contains. -Otherwise, we return the URL we originally got. Right now this supports .url, -.webloc and .ftploc files. -*/ -+(NSURL*) decodeLocalFileURL:(NSURL*)url -{ - NSString *urlPathString = [url path]; - NSString *ext = [[urlPathString pathExtension] lowercaseString]; - OSType fileType = NSHFSTypeCodeFromFileType(NSHFSTypeOfFile(urlPathString)); - - if ([ext isEqualToString:@"url"] || fileType == 'LINK') - url = [NSURL URLFromIEURLFile:urlPathString]; - else if ([ext isEqualToString:@"webloc"] || [ext isEqualToString:@"ftploc"] || fileType == 'ilht' || fileType == 'ilft') - url = [NSURL URLFromInetloc:urlPathString]; - - return url; -} - -+(BOOL) isBlankURL:(NSString*)inURL +// +// Open URL service handler +// +- (void)openURL:(NSPasteboard*)pboard userData:(NSString*)userData error:(NSString**)error { - BOOL isBlank = NO; - if (!inURL || [inURL isEqualToString: @"about:blank"] || [inURL isEqualToString: @""]) - isBlank = YES; - return isBlank; + NSArray* types = [pboard types]; + if (![types containsObject:NSStringPboardType]) { + *error = NSLocalizedString(@"Error: couldn't open URL.", + @"pboard couldn't give URL string."); + return; + } + NSString* urlString = [pboard stringForType:NSStringPboardType]; + if (!urlString) { + *error = NSLocalizedString(@"Error: couldn't open URL.", + @"pboard couldn't give URL string."); + return; + } + + // check to see if it's a bookmark keyword + NSArray* resolvedURLs = [[BookmarkManager sharedBookmarkManager] resolveBookmarksKeyword:urlString]; + + if (resolvedURLs) { + if ([resolvedURLs count] == 1) + [self openNewWindowOrTabWithURL:[resolvedURLs lastObject] andReferrer:nil alwaysInFront:YES]; + else + [self openBrowserWindowWithURLs:resolvedURLs behind:nil allowPopups:NO]; + } + else { + urlString = [urlString stringByRemovingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + [self openNewWindowOrTabWithURL:urlString andReferrer:nil alwaysInFront:YES]; + } } --(IBAction)newWindow:(id)aSender +#pragma mark - +#pragma mark Delegate/Notification + +- (BOOL)applicationShouldHandleReopen:(NSApplication*)theApp hasVisibleWindows:(BOOL)flag +{ + // we might be sitting there with the "there is another copy of camino running" dialog up + // (which means we're in a modal loop in [PreferenceManager init]). So if we haven't + // finished initting prefs yet, just bail. + if (![PreferenceManager sharedInstanceDontCreate]) + return NO; + + // ignore |hasVisibleWindows| because we always want to show a browser window when + // the user clicks on the app icon, even if, say, prefs or the d/l window are open. + // If there is no browser, create one. If there is one, unminimize it if it's in the dock. + NSWindow* frontBrowser = [self getFrontmostBrowserWindow]; + if (!frontBrowser) + [self newWindow:self]; + else if ([frontBrowser isMiniaturized]) + [frontBrowser deminiaturize:self]; + + return NO; +} + +- (void)applicationDidChangeScreenParameters:(NSNotification*)aNotification +{ + [NSApp makeWindowsPerform:@selector(display) inOrder:YES]; +} + +- (void)applicationDidBecomeActive:(NSNotification*)aNotification +{ + [mFindDialog applicationWasActivated]; +} + +- (void)windowLayeringDidChange:(NSNotification*)inNotification +{ + [self delayedAdjustBookmarksMenuItemsEnabling]; + [self delayedFixCloseMenuItemKeyEquivalents]; + [self delayedUpdatePageInfo]; +} + +#pragma mark - +#pragma mark - +#pragma mark Application Menu + +// +// -aboutWindow: +// +// Show the (slightly modified) standard about window, with the build id instead of the +// typical application version. It'll display like "2003120403 (v0.7+)". +// +- (IBAction)aboutWindow:(id)sender +{ + NSString* version = [NSString stringWithFormat:@"%010u", NS_BUILD_ID]; + NSDictionary* d = [NSDictionary dictionaryWithObject:version forKey:@"ApplicationVersion"]; + [NSApp orderFrontStandardAboutPanelWithOptions:d]; +} + +- (IBAction)feedbackLink:(id)aSender +{ + NSString* pageToLoad = NSLocalizedStringFromTable(@"FeedbackPageDefault", @"WebsiteDefaults", nil); + if (![pageToLoad isEqualToString:@"FeedbackPageDefault"]) + [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; +} + +- (IBAction)displayPreferencesWindow:(id)sender +{ + [[MVPreferencesController sharedInstance] showPreferences:nil]; +} + +// +// -resetBrowser: +// +// Here we need to: +// - warn user about what is going to happen +// - if its OK... +// - close all open windows, delete cache, history, cookies, site permissions, +// downloads, saved names and passwords, and clear Top 10 group in bookmarks +// +- (IBAction)resetBrowser:(id)sender +{ + if (NSRunCriticalAlertPanel(NSLocalizedString(@"Reset Camino Title", nil), + NSLocalizedString(@"Reset Warning Message", nil), + NSLocalizedString(@"Reset Camino", nil), + NSLocalizedString(@"CancelButtonText", nil), + nil) == NSAlertDefaultReturn) + { + + // close all windows + NSArray* openWindows = [[NSApp orderedWindows] copy]; + NSEnumerator* windowEnum = [openWindows objectEnumerator]; + NSWindow* curWindow; + while ((curWindow = [windowEnum nextObject])) { + // we don't want the "you are closing a window with multiple tabs" warning to show up. + if ([[curWindow windowController] isMemberOfClass:[BrowserWindowController class]]) + [(BrowserWindowController*)[curWindow windowController] setWindowClosesQuietly:YES]; + + if ([curWindow isVisible] || [curWindow isMiniaturized]) + [curWindow performClose:self]; + } + [openWindows release]; + + // remove cache + nsCOMPtr cacheServ (do_GetService("@mozilla.org/network/cache-service;1")); + if (cacheServ) + cacheServ->EvictEntries(nsICache::STORE_ANYWHERE); + + // remove cookies + nsCOMPtr cm(do_GetService(NS_COOKIEMANAGER_CONTRACTID)); + nsICookieManager* mCookieManager = cm.get(); + if (mCookieManager) + mCookieManager->RemoveAll(); + + // remove site permissions + nsCOMPtr pm(do_GetService(NS_PERMISSIONMANAGER_CONTRACTID)); + nsIPermissionManager* mPermissionManager = pm.get(); + if (mPermissionManager) + mPermissionManager->RemoveAll(); + + // remove history + nsCOMPtr hist (do_GetService("@mozilla.org/browser/global-history;2")); + if (hist) + hist->RemoveAllPages(); + + // remove downloads + [[ProgressDlgController sharedDownloadController] clearAllDownloads]; + +#if 0 // disable this for now (see bug 3202080) + // remove saved names and passwords + [[KeychainService instance] removeAllUsernamesAndPasswords]; +#endif + + // re-set all bookmarks visit counts to zero + [[BookmarkManager sharedBookmarkManager] clearAllVisits]; + + // open a new window + [self newWindow:self]; + } +} + +// +// -emptyCache: +// +// Puts up a modal panel and if the user gives the go-ahead, emtpies the disk and memory +// caches. We keep this separate from |-resetBrowser:| so the user can just clear the cache +// and not have to delete everything (such as their keychain passwords). +// +- (IBAction)emptyCache:(id)sender +{ + if (NSRunCriticalAlertPanel(NSLocalizedString(@"EmptyCacheTitle", nil), + NSLocalizedString(@"EmptyCacheMessage", nil), + NSLocalizedString(@"EmptyButton", nil), + NSLocalizedString(@"CancelButtonText", nil), nil) == NSAlertDefaultReturn) + { + // remove cache + nsCOMPtr cacheServ (do_GetService("@mozilla.org/network/cache-service;1")); + if (cacheServ) + cacheServ->EvictEntries(nsICache::STORE_ANYWHERE); + } +} + +#pragma mark - +#pragma mark File Menu + +- (IBAction)newWindow:(id)aSender { // If we have a key window, have it autosave its dimensions before // we open a new window. That ensures the size ends up matching. @@ -614,22 +915,21 @@ Otherwise, we return the URL we originally got. Right now this supports .url, if ([MainController isBlankURL:homePage]) [controller focusURLBar]; else - [[[controller getBrowserWrapper] getBrowserView] setActive: YES]; + [[[controller getBrowserWrapper] getBrowserView] setActive:YES]; // Only load the command-line specified URL for the first window we open if (mStartURL) { [mStartURL release]; mStartURL = nil; } -} +} --(IBAction)newTab:(id)aSender +- (IBAction)newTab:(id)aSender { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) [browserController newTab:aSender]; - else - { + else { // follow the pref about what to load in a new tab (even though we're making a new window) int newTabPage = [[PreferenceManager sharedInstance] getIntPref:"browser.tabs.startPage" withSuccess:NULL]; BOOL loadHomepage = (newTabPage == 1); @@ -642,10 +942,99 @@ Otherwise, we return the URL we originally got. Right now this supports .url, } } +- (IBAction)openFile:(id)aSender +{ + NSOpenPanel* openPanel = [NSOpenPanel openPanel]; + [openPanel setCanChooseFiles:YES]; + [openPanel setCanChooseDirectories:NO]; + [openPanel setAllowsMultipleSelection:YES]; + NSArray* fileTypes = [NSArray arrayWithObjects:@"htm",@"html",@"shtml",@"xhtml",@"xml", + @"txt",@"text", + @"gif",@"jpg",@"jpeg",@"png",@"bmp",@"svg",@"svgz", + @"webloc",@"ftploc",@"url", + NSFileTypeForHFSTypeCode('ilht'), + NSFileTypeForHFSTypeCode('ilft'), + NSFileTypeForHFSTypeCode('LINK'), + nil]; + + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) { + [openPanel beginSheetForDirectory:nil + file:nil + types:fileTypes + modalForWindow:[browserController window] + modalDelegate:self + didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) + contextInfo:browserController]; + } + else { + int result = [openPanel runModalForTypes:fileTypes]; + [self openPanelDidEnd:openPanel returnCode:result contextInfo:nil]; + } +} + +- (void)openPanelDidEnd:(NSOpenPanel*)inOpenPanel returnCode:(int)inReturnCode contextInfo:(void*)inContextInfo +{ + if (inReturnCode != NSOKButton) + return; + + BrowserWindowController* browserController = (BrowserWindowController*)inContextInfo; + + NSArray* urlArray = [inOpenPanel URLs]; + if ([urlArray count] == 0) + return; + + NSMutableArray* urlStringsArray = [NSMutableArray arrayWithCapacity:[urlArray count]]; + + // fix them up + NSEnumerator* urlsEnum = [urlArray objectEnumerator]; + NSURL* curURL; + while ((curURL = [urlsEnum nextObject])) { + [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:curURL]; + curURL = [MainController decodeLocalFileURL:curURL]; + [urlStringsArray addObject:[curURL absoluteString]]; + } + + if (!browserController) + [self openBrowserWindowWithURLs:urlStringsArray behind:nil allowPopups:YES]; + else + [browserController openURLArray:urlStringsArray tabOpenPolicy:eReplaceFromCurrentTab allowPopups:YES]; +} + +- (IBAction)openLocation:(id)aSender +{ + NSWindow* browserWindow = [self getFrontmostBrowserWindow]; + if (!browserWindow) { + [self openBrowserWindowWithURL:@"about:blank" andReferrer:nil behind:nil allowPopups:NO]; + browserWindow = [mApplication mainWindow]; + } + else if (![browserWindow isMainWindow] || ![browserWindow isKeyWindow]) { + [browserWindow makeKeyAndOrderFront:self]; + } + + [[browserWindow windowController] performAppropriateLocationAction]; +} + +- (IBAction)doSearch:(id)aSender +{ + NSWindow* browserWindow = [self getFrontmostBrowserWindow]; + + if (browserWindow) { + if (![browserWindow isMainWindow]) + [browserWindow makeKeyAndOrderFront:self]; + } + else { + [self newWindow:self]; + browserWindow = [self getFrontmostBrowserWindow]; + } + + [[browserWindow windowController] performAppropriateSearchAction]; +} + // // Closes all windows (including minimized windows), respecting the "warn before closing multiple tabs" pref // --(IBAction)closeAllWindows:(id)aSender +- (IBAction)closeAllWindows:(id)aSender { BOOL doCloseWindows = YES; PreferenceManager* prefManager = [PreferenceManager sharedInstance]; @@ -665,7 +1054,8 @@ Otherwise, we return the URL we originally got. Right now this supports .url, closeAlertExpl = [NSString stringWithFormat:NSLocalizedString(@"CloseWindowWithMultipleTabsExplFormat", @""), numTabs]; } - } else if ([openBrowserWins count] > 1) { + } + else if ([openBrowserWins count] > 1) { closeAlertMsg = NSLocalizedString(@"CloseMultipleWindowsMsg", @""); closeAlertExpl = [NSString stringWithFormat:NSLocalizedString(@"CloseMultipleWindowsExpl", @""), [openBrowserWins count]]; @@ -699,167 +1089,102 @@ Otherwise, we return the URL we originally got. Right now this supports .url, NSArray* windows = [NSApp windows]; NSEnumerator* windowEnum = [windows objectEnumerator]; NSWindow* curWindow; - while (curWindow = [windowEnum nextObject]) + while (curWindow = [windowEnum nextObject]) [curWindow close]; } } --(IBAction)closeTab:(id)aSender +- (IBAction)closeTab:(id)aSender { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) [browserController closeCurrentTab:aSender]; } --(IBAction) previousTab:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - [browserController previousTab:aSender]; -} - --(IBAction) nextTab:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - [browserController nextTab:aSender]; -} - --(IBAction) openFile:(id)aSender -{ - NSOpenPanel* openPanel = [NSOpenPanel openPanel]; - [openPanel setCanChooseFiles:YES]; - [openPanel setCanChooseDirectories:NO]; - [openPanel setAllowsMultipleSelection:YES]; - NSArray* fileTypes = [NSArray arrayWithObjects: @"htm",@"html",@"shtml",@"xhtml",@"xml", - @"txt",@"text", - @"gif",@"jpg",@"jpeg",@"png",@"bmp",@"svg",@"svgz", - @"webloc",@"ftploc",@"url", - NSFileTypeForHFSTypeCode('ilht'), - NSFileTypeForHFSTypeCode('ilft'), - NSFileTypeForHFSTypeCode('LINK'), - nil]; - - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - { - [openPanel beginSheetForDirectory:nil - file:nil - types:fileTypes - modalForWindow:[browserController window] - modalDelegate:self - didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:) - contextInfo:browserController]; - } - else - { - int result = [openPanel runModalForTypes:fileTypes]; - [self openPanelDidEnd:openPanel returnCode:result contextInfo:nil]; - } -} - -- (void)openPanelDidEnd:(NSOpenPanel*)inOpenPanel returnCode:(int)inReturnCode contextInfo:(void*)inContextInfo -{ - if (inReturnCode != NSOKButton) - return; - - BrowserWindowController* browserController = (BrowserWindowController*)inContextInfo; - - NSArray* urlArray = [inOpenPanel URLs]; - if ([urlArray count] == 0) - return; - - NSMutableArray* urlStringsArray = [NSMutableArray arrayWithCapacity:[urlArray count]]; - - // fix them up - NSEnumerator* urlsEnum = [urlArray objectEnumerator]; - NSURL* curURL; - while ((curURL = [urlsEnum nextObject])) - { - [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:curURL]; - curURL = [MainController decodeLocalFileURL:curURL]; - [urlStringsArray addObject:[curURL absoluteString]]; - } - - if (!browserController) - { - [self openBrowserWindowWithURLs:urlStringsArray behind:nil allowPopups:YES]; - } - else - { - [browserController openURLArray:urlStringsArray tabOpenPolicy:eReplaceFromCurrentTab allowPopups:YES]; - } -} - --(IBAction) openLocation:(id)aSender -{ - NSWindow* browserWindow = [self getFrontmostBrowserWindow]; - if (!browserWindow) { - [self openBrowserWindowWithURL: @"about:blank" andReferrer:nil behind:nil allowPopups:NO]; - browserWindow = [mApplication mainWindow]; - } - else if (![browserWindow isMainWindow] || ![browserWindow isKeyWindow]) { - [browserWindow makeKeyAndOrderFront:self]; - } - - [[browserWindow windowController] performAppropriateLocationAction]; -} - --(IBAction) savePage:(id)aSender +- (IBAction)savePage:(id)aSender { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) [browserController saveDocument:NO filterView:[self getSavePanelView]]; } --(IBAction) pageSetup:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - [browserController pageSetup:aSender]; -} - --(IBAction) printPage:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - [browserController printDocument:aSender]; -} - --(IBAction) toggleOfflineMode:(id)aSender -{ - nsCOMPtr ioService(do_GetService(ioServiceContractID)); - if (!ioService) - return; - PRBool offline = PR_FALSE; - ioService->GetOffline(&offline); - ioService->SetOffline(!offline); - mOffline = !offline; - - // Update the menu item text. - // Set the menu item's text to "Go Online" if we're currently - // offline. -/* - if (mOffline) - [mOfflineMenuItem setTitle: @"Go Online"]; - else - [mOfflineMenuItem setTitle: @"Work Offline"]; -*/ - - // Indicate that we are working offline. - [[NSNotificationCenter defaultCenter] postNotificationName:@"offlineModeChanged" object:nil]; -} - - (IBAction)sendURL:(id)aSender { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) [browserController sendURL:aSender]; } +- (IBAction)importBookmarks:(id)aSender +{ + [[BookmarkManager sharedBookmarkManager] startImportBookmarks]; +} +- (IBAction)exportBookmarks:(id)aSender +{ + NSSavePanel* savePanel = [NSSavePanel savePanel]; + [savePanel setPrompt:NSLocalizedString(@"Export", @"Export")]; + [savePanel setRequiredFileType:@"html"]; + [savePanel setCanSelectHiddenExtension:YES]; -// Edit menu actions. + // get an accessory view for HTML or Safari .plist output + if (!mExportPanelView) + [NSBundle loadNibNamed:@"AccessoryViews" owner:self]; + NSPopUpButton* button = [mExportPanelView viewWithTag:1001]; + [[button itemAtIndex:0] setRepresentedObject:savePanel]; + [[button itemAtIndex:1] setRepresentedObject:savePanel]; + [savePanel setAccessoryView:mExportPanelView]; + // start the save panel + int saveResult = [savePanel runModalForDirectory:nil file:NSLocalizedString(@"ExportedBookmarkFile", @"Exported Bookmarks")]; + int selectedButton = [button indexOfSelectedItem]; + if (saveResult != NSFileHandlingPanelOKButton) + return; + if (0 == selectedButton) + [[BookmarkManager sharedBookmarkManager] writeHTMLFile:[savePanel filename]]; + else + [[BookmarkManager sharedBookmarkManager] writeSafariFile:[savePanel filename]]; +} + +- (IBAction)pageSetup:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) + [browserController pageSetup:aSender]; +} + +- (IBAction)printPage:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) + [browserController printDocument:aSender]; +} + +- (IBAction)toggleOfflineMode:(id)aSender +{ + nsCOMPtr ioService(do_GetService(ioServiceContractID)); + if (!ioService) + return; + PRBool offline = PR_FALSE; + ioService->GetOffline(&offline); + ioService->SetOffline(!offline); + mOffline = !offline; + + // Update the menu item text. + // Set the menu item's text to "Go Online" if we're currently + // offline. +/* + if (mOffline) + [mOfflineMenuItem setTitle:@"Go Online"]; + else + [mOfflineMenuItem setTitle:@"Work Offline"]; +*/ + + // Indicate that we are working offline. + [[NSNotificationCenter defaultCenter] postNotificationName:@"offlineModeChanged" object:nil]; +} + +#pragma mark - +#pragma mark Edit Menu // // -findInPage @@ -867,42 +1192,76 @@ Otherwise, we return the URL we originally got. Right now this supports .url, // Called in response to "Find" in edit menu. Opens the find dialog. We only keep // one around for the whole app to use, showing/hiding as we see fit. // --(IBAction) findInPage:(id)aSender +- (IBAction)findInPage:(id)aSender { - if ( !mFindDialog ) - mFindDialog = [[FindDlgController alloc] initWithWindowNibName: @"FindDialog"]; + if (!mFindDialog) + mFindDialog = [[FindDlgController alloc] initWithWindowNibName:@"FindDialog"]; [mFindDialog showWindow:self]; } --(IBAction) goBack:(id)aSender +#pragma mark - +#pragma mark View Menu + +- (IBAction)toggleBookmarksToolbar:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (!browserController) + return; + + float height = [[browserController bookmarkToolbar] frame].size.height; + BOOL showToolbar = (BOOL)(!(height > 0)); + + [[browserController bookmarkToolbar] showBookmarksToolbar:showToolbar]; + + // save prefs here + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + [defaults setInteger:((showToolbar) ? 0 : 1) forKey:USER_DEFAULTS_HIDE_PERS_TOOLBAR_KEY]; +} + +- (IBAction)doStop:(id)aSender { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) - [browserController back: aSender]; + [browserController stop:aSender]; } --(IBAction) goForward:(id)aSender +- (IBAction)doReload:(id)aSender { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) - [browserController forward: aSender]; + [browserController reload:aSender]; } --(IBAction) doReload:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - [browserController reload: aSender]; -} - --(IBAction) doReloadAllTabs:(id)aSender +- (IBAction)doReloadAllTabs:(id)aSender { BrowserWindowController* browserController = [self getMainWindowBrowserController]; if (browserController) [browserController reloadAllTabs:aSender]; } --(IBAction) reloadWithCharset:(id)aSender +- (IBAction)makeTextBigger:(id)aSender +{ + [[self getMainWindowBrowserController] makeTextBigger:aSender]; +} + +- (IBAction)makeTextDefaultSize:(id)aSender +{ + [[self getMainWindowBrowserController] makeTextDefaultSize:aSender]; +} + +- (IBAction)makeTextSmaller:(id)aSender +{ + [[self getMainWindowBrowserController] makeTextSmaller:aSender]; +} + +- (IBAction)viewSource:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) + [browserController viewPageSource:aSender]; // top-level page, not focussed frame +} + +- (IBAction)reloadWithCharset:(id)aSender { // Figure out which charset to tell gecko to load based on the sender's tag. There // is guaranteed to only be 1 key that matches this tag, so we just take the first one. @@ -914,7 +1273,7 @@ Otherwise, we return the URL we originally got. Right now this supports .url, } } --(IBAction) toggleAutoCharsetDetection:(id)aSender +- (IBAction)toggleAutoCharsetDetection:(id)aSender { NSString* detectorValue = [[PreferenceManager sharedInstance] getStringPref:"intl.charset.detector" withSuccess:NULL]; BOOL universalChardetOn = [detectorValue isEqualToString:@"universal_charset_detector"]; @@ -924,20 +1283,16 @@ Otherwise, we return the URL we originally got. Right now this supports .url, [self doReload:nil]; } --(IBAction) doStop:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - [browserController stop: aSender]; -} +#pragma mark - +#pragma mark History Menu --(IBAction) goHome:(id)aSender +- (IBAction)goHome:(id)aSender { NSWindow* browserWindow = [self getFrontmostBrowserWindow]; if (browserWindow) { if (![browserWindow isMainWindow]) [browserWindow makeKeyAndOrderFront:self]; - + [[browserWindow windowController] home:aSender]; } else { @@ -949,22 +1304,143 @@ Otherwise, we return the URL we originally got. Right now this supports .url, } } --(IBAction) doSearch:(id)aSender +- (IBAction)goBack:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) + [browserController back:aSender]; +} + +- (IBAction)goForward:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) + [browserController forward:aSender]; +} + +// +// -showHistory: +// +// show the history in the bookmark manager. Creates a new window if +// one isn't already there. history isn't a toggle, hence the name. +// +- (IBAction)showHistory:(id)aSender { NSWindow* browserWindow = [self getFrontmostBrowserWindow]; - if (browserWindow) { if (![browserWindow isMainWindow]) [browserWindow makeKeyAndOrderFront:self]; - } else { - [self newWindow:self]; - browserWindow = [self getFrontmostBrowserWindow]; + } + else { + [self newWindow:self]; + browserWindow = [mApplication mainWindow]; } - [[browserWindow windowController] performAppropriateSearchAction]; + [[browserWindow windowController] manageHistory:aSender]; } --(IBAction) downloadsWindow:(id)aSender +// +// -clearHistory: +// +// clear the global history, after showing a warning +// +- (IBAction)clearHistory:(id)aSender +{ + if (NSRunCriticalAlertPanel(NSLocalizedString(@"ClearHistoryTitle", nil), + NSLocalizedString(@"ClearHistoryMessage", nil), + NSLocalizedString(@"ClearHistoryButton", nil), + NSLocalizedString(@"CancelButtonText", nil), + nil) == NSAlertDefaultReturn) + { + // clear history + nsCOMPtr hist = do_GetService("@mozilla.org/browser/global-history;2"); + if (hist) + hist->RemoveAllPages(); + } +} + +#pragma mark - +#pragma mark Bookmarks Menu + +// +// manageBookmarks: +// +// toggle the bookmark manager (creating a new window if needed) +// +- (IBAction)manageBookmarks:(id)aSender +{ + NSWindow* browserWindow = [self getFrontmostBrowserWindow]; + if (browserWindow) { + if (![browserWindow isMainWindow]) + [browserWindow makeKeyAndOrderFront:self]; + } + else { + [self newWindow:self]; + browserWindow = [mApplication mainWindow]; + } + + [[browserWindow windowController] manageBookmarks:aSender]; +} + +- (IBAction)openMenuBookmark:(id)aSender +{ + BookmarkItem* item = [aSender representedObject]; + EBookmarkOpenBehavior openBehavior = eBookmarkOpenBehavior_Preferred; + BOOL reverseBackgroundPref = NO; + + if ([aSender isAlternate]) { + reverseBackgroundPref = ([aSender keyEquivalentModifierMask] & NSShiftKeyMask) != 0; + if ([aSender keyEquivalentModifierMask] & NSCommandKeyMask) + openBehavior = eBookmarkOpenBehavior_NewPreferred; + } + // safeguard for bookmark menus that don't have alternates yet + else if ([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) + openBehavior = eBookmarkOpenBehavior_NewPreferred; + + [self loadBookmark:item withBWC:[self getMainWindowBrowserController] openBehavior:openBehavior reverseBgToggle:reverseBackgroundPref]; +} + +- (IBAction)aboutServers:(id)aSender +{ + NSString* pageToLoad = NSLocalizedStringFromTable(@"RendezvousPageDefault", @"WebsiteDefaults", nil); + if (![pageToLoad isEqualToString:@"RendezvousPageDefault"]) + [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; +} + +- (IBAction)connectToServer:(id)aSender +{ + [[NetworkServices sharedNetworkServices] attemptResolveService:[aSender tag] forSender:self]; +} + +#pragma mark - +#pragma mark Window Menu + +- (IBAction)zoomAll:(id)aSender +{ + NSArray* windows = [NSApp windows]; + NSEnumerator* windowEnum = [windows objectEnumerator]; + NSWindow* curWindow; + + while (curWindow = [windowEnum nextObject]) + if ([[curWindow windowController] isMemberOfClass:[BrowserWindowController class]]) + [curWindow zoom:aSender]; +} + +- (IBAction)previousTab:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) + [browserController previousTab:aSender]; +} + +- (IBAction)nextTab:(id)aSender +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) + [browserController nextTab:aSender]; +} + +- (IBAction)downloadsWindow:(id)aSender { ProgressDlgController* dlgController = [ProgressDlgController sharedDownloadController]; // If the frontmost window is the downloads window, close it. Otherwise open or bring downloads window to front. @@ -974,24 +1450,216 @@ Otherwise, we return the URL we originally got. Right now this supports .url, [dlgController showWindow:aSender]; } +#pragma mark - +#pragma mark Help Menu + +- (IBAction)supportLink:(id)aSender +{ + NSString* pageToLoad = NSLocalizedStringFromTable(@"SupportPageDefault", @"WebsiteDefaults", nil); + if (![pageToLoad isEqualToString:@"SupportPageDefault"]) + [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; +} + +- (IBAction)infoLink:(id)aSender +{ + NSString* pageToLoad = NSLocalizedStringFromTable(@"InfoPageDefault", @"WebsiteDefaults", nil); + if (![pageToLoad isEqualToString:@"InfoPageDefault"]) + [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; +} + +- (IBAction)aboutPlugins:(id)aSender +{ + [self openNewWindowOrTabWithURL:@"about:plugins" andReferrer:nil alwaysInFront:YES]; +} + +- (IBAction)releaseNoteLink:(id)aSender +{ + NSString* pageToLoad = NSLocalizedStringFromTable(@"ReleaseNotesDefault", @"WebsiteDefaults", nil); + if (![pageToLoad isEqualToString:@"ReleaseNotesDefault"]) + [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; +} + +- (IBAction)tipsTricksLink:(id)aSender +{ + NSString* pageToLoad = NSLocalizedStringFromTable(@"TipsTricksPageDefault", @"WebsiteDefaults", nil); + if (![pageToLoad isEqualToString:@"TipsTricksPageDefault"]) + [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; +} + +- (IBAction)searchCustomizeLink:(id)aSender +{ + NSString* pageToLoad = NSLocalizedStringFromTable(@"SearchCustomPageDefault", @"WebsiteDefaults", nil); + if (![pageToLoad isEqualToString:@"SearchCustomPageDefault"]) + [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; +} + +#pragma mark - +#pragma mark Menu Maintenance + +- (BOOL)validateMenuItem:(NSMenuItem*)aMenuItem +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + SEL action = [aMenuItem action]; + + // NSLog(@"MainController validateMenuItem for %@ (%s)", [aMenuItem title], action); + + // disable items that aren't relevant if there's no main browser window open + // or the bookmark/history manager is open + // XXX some of these should be wired to the First Responder (like reload:). + if (action == @selector(printPage:) || + /* ... many more items go here ... */ + action == @selector(pageSetup:) || + action == @selector(findInPage:) || + action == @selector(savePage:)) + { + return (browserController && ![browserController bookmarkManagerIsVisible]); + } + + if (action == @selector(doReload:)) + return (browserController && [[browserController getBrowserWrapper] canReload]); + + if (action == @selector(doReloadAllTabs:)) + return (browserController != nil); + + // disable open menu items if a sheet is up (maybe disable others too) + if (action == @selector(openFile:) || + action == @selector(openLocation:)) { + return (!browserController || [[browserController window] attachedSheet] == nil); + } + + // check what the state of the personal toolbar should be, but only if there is a browser + // window open. Popup windows that have the personal toolbar removed should always gray + // out this menu. + if (action == @selector(toggleBookmarksToolbar:)) { + if (browserController) { + NSView* bookmarkToolbar = [browserController bookmarkToolbar]; + if (bookmarkToolbar) { + float height = [bookmarkToolbar frame].size.height; + BOOL toolbarShowing = (height > 0); + if (toolbarShowing) + [mBookmarksToolbarMenuItem setTitle:NSLocalizedString(@"Hide Bookmarks Toolbar",@"")]; + else + [mBookmarksToolbarMenuItem setTitle:NSLocalizedString(@"Show Bookmarks Toolbar",@"")]; + return YES; + } + } + return NO; + } + + // only enable newTab if there is a browser window frontmost, or if there is no window + // (i.e. disable it for non-browser windows). + if (action == @selector(newTab:)) + return (browserController || ![NSApp mainWindow]); + + if (action == @selector(closeTab:)) { + BrowserWindowController* keyBWC = [self getKeyWindowBrowserController]; + return (keyBWC && [[keyBWC getTabBrowser] numberOfTabViewItems] > 1); + } + + // only activate if we've got multiple tabs open. + if (action == @selector(nextTab:) || action == @selector(previousTab:)) + return (browserController && [[browserController getTabBrowser] numberOfTabViewItems] > 1); + + if (action == @selector(makeTextBigger:)) + return (browserController && [browserController canMakeTextBigger]); + + if (action == @selector(makeTextSmaller:)) + return (browserController && [browserController canMakeTextSmaller]); + + if (action == @selector(makeTextDefaultSize:)) + return (browserController && [browserController canMakeTextDefaultSize]); + + // don't allow View Source on the bookmark manager or on non-text content + if (action == @selector(viewSource:)) { + return (browserController && + ![browserController bookmarkManagerIsVisible] && + [[[browserController getBrowserWrapper] getBrowserView] isTextBasedContent]); + } + + if (action == @selector(doStop:)) + return (browserController && [[browserController getBrowserWrapper] isBusy]); + + if (action == @selector(goBack:) || action == @selector(goForward:)) { + if (browserController) { + CHBrowserView* browserView = [[browserController getBrowserWrapper] getBrowserView]; + if (action == @selector(goBack:)) + return [browserView canGoBack]; + else if (action == @selector(goForward:)) + return [browserView canGoForward]; + } + return NO; + } + + if (action == @selector(manageBookmarks:)) { + BOOL showingBookmarks = (browserController && [browserController bookmarkManagerIsVisible]); + NSString* showBMLabel = showingBookmarks ? NSLocalizedString(@"Hide All Bookmarks", @"") + : NSLocalizedString(@"Show All Bookmarks", @""); + [aMenuItem setTitle:showBMLabel]; + return showingBookmarks ? [browserController canHideBookmarks] : YES; + } + + if (action == @selector(sendURL:)) + return ![[[browserController getBrowserWrapper] getCurrentURI] hasPrefix:@"about:"]; + + // key alternates + if (action == @selector(openMenuBookmark:) && [aMenuItem isAlternate]) { + if ([[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.opentabfor.middleclick" withSuccess:NULL]) + [aMenuItem setTitle:NSLocalizedString(@"Open in New Tabs", nil)]; + else + [aMenuItem setTitle:NSLocalizedString(@"Open in Tabs in New Window", nil)]; + } + + // default return + return YES; +} + - (void)menuWillDisplay:(NSNotification*)inNotification { if ([mBookmarksMenu isTargetOfMenuDisplayNotification:[inNotification object]]) - { [self adjustBookmarkMenuItems]; - } else if ([mTextEncodingsMenu isTargetOfMenuDisplayNotification:[inNotification object]]) - { [self adjustTextEncodingMenu]; +} + +- (void)adjustTextEncodingMenu +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + if (browserController) { + // enable all items + [mTextEncodingsMenu setAllItemsEnabled:YES startingWithItemAtIndex:0 includingSubmenus:YES]; + + NSString* charset = [browserController currentCharset]; +#if DEBUG_CHARSET + NSLog(@"charset is %@", charset); +#endif + NSNumber* tag = [mCharsets objectForKey:[charset lowercaseString]]; + [mTextEncodingsMenu checkItemWithTag:[tag intValue] uncheckingOtherItems:YES]; } + else { + [mTextEncodingsMenu setAllItemsEnabled:NO startingWithItemAtIndex:0 includingSubmenus:YES]; + // always enable the autodetect item + [[mTextEncodingsMenu itemWithTag:kEncodingMenuAutodetectItemTag] setEnabled:YES]; + } + + // update the state of the autodetect item + NSString* detectorValue = [[PreferenceManager sharedInstance] getStringPref:"intl.charset.detector" withSuccess:NULL]; + BOOL universalChardetOn = [detectorValue isEqualToString:@"universal_charset_detector"]; + [[mTextEncodingsMenu itemWithTag:kEncodingMenuAutodetectItemTag] setState:(universalChardetOn ? NSOnState : NSOffState)]; +} + +- (void)adjustBookmarkMenuItems +{ + BOOL enableItems = [self bookmarksItemsEnabled]; + + int firstBookmarkItem = [mBookmarksMenu indexOfItemWithTag:kBookmarksDividerTag] + 1; + [mBookmarksMenu setAllItemsEnabled:enableItems startingWithItemAtIndex:firstBookmarkItem includingSubmenus:YES]; } - (void)delayedAdjustBookmarksMenuItemsEnabling - { - // we do this after a delay to ensure that window layer state has been set by the time - // we do the enabling. - if (!mBookmarksMenuUpdatePending) - { +{ + // we do this after a delay to ensure that window layer state has been set by the time + // we do the enabling. + if (!mBookmarksMenuUpdatePending) { [self performSelector:@selector(doBookmarksMenuEnabling) withObject:nil afterDelay:0]; mBookmarksMenuUpdatePending = YES; } @@ -1032,11 +1700,6 @@ Otherwise, we return the URL we originally got. Right now this supports .url, mBookmarksMenuUpdatePending = NO; } -- (NSMenu*)bookmarksMenu -{ - return mBookmarksMenu; -} - - (BOOL)bookmarksItemsEnabled { // since this menu is not in the menu bar, we have to update it by hand @@ -1044,346 +1707,10 @@ Otherwise, we return the URL we originally got. Right now this supports .url, return [[mBookmarksHelperMenu itemWithTarget:self andAction:@selector(openMenuBookmark:)] isEnabled]; } -- (void)adjustBookmarkMenuItems -{ - BOOL enableItems = [self bookmarksItemsEnabled]; - - int firstBookmarkItem = [mBookmarksMenu indexOfItemWithTag:kBookmarksDividerTag] + 1; - [mBookmarksMenu setAllItemsEnabled:enableItems startingWithItemAtIndex:firstBookmarkItem includingSubmenus:YES]; -} - -- (NSView*)getSavePanelView -{ - if (!mFilterView) - { - // note that this will cause our -awakeFromNib to get called again - [NSBundle loadNibNamed:@"AccessoryViews" owner:self]; - } - return mFilterView; -} - -- (NSArray*)browserWindows -{ - NSEnumerator* windowEnum = [[NSApp orderedWindows] objectEnumerator]; - NSMutableArray* windowArray = [NSMutableArray array]; - - NSWindow* curWindow; - while ((curWindow = [windowEnum nextObject])) - { - // not all browser windows are created equal. We only consider those with - // an empty chrome mask, or ones with a toolbar, status bar, and resize control - // to be real top-level browser windows for purposes of saving size and - // loading urls in. Others are popups and are transient. - if (([curWindow isVisible] || [curWindow isMiniaturized] || [NSApp isHidden]) && - [[curWindow windowController] isMemberOfClass:[BrowserWindowController class]] && - [[curWindow windowController] hasFullBrowserChrome]) - { - [windowArray addObject:curWindow]; - } - } - - return windowArray; -} - -- (NSWindow*)getFrontmostBrowserWindow -{ - // for some reason, [NSApp mainWindow] doesn't always work, so we have to - // do this manually - NSEnumerator* windowEnum = [[NSApp orderedWindows] objectEnumerator]; - NSWindow* foundWindow = nil; - - NSWindow* curWindow; - while ((curWindow = [windowEnum nextObject])) - { - // not all browser windows are created equal. We only consider those with - // an empty chrome mask, or ones with a toolbar, status bar, and resize control - // to be real top-level browser windows for purposes of saving size and - // loading urls in. Others are popups and are transient. - if (([curWindow isVisible] || [curWindow isMiniaturized] || [NSApp isHidden]) && - [[curWindow windowController] isMemberOfClass:[BrowserWindowController class]] && - [[curWindow windowController] hasFullBrowserChrome]) - { - foundWindow = curWindow; - break; - } - } - - return foundWindow; -} - -- (BrowserWindowController*)openBrowserWindowWithURL:(NSString*)aURL andReferrer:(NSString*)aReferrer behind:(NSWindow*)window allowPopups:(BOOL)inAllowPopups -{ - BrowserWindowController* browser = [[BrowserWindowController alloc] initWithWindowNibName: @"BrowserWindow"]; - - if (window) - { - BrowserWindow* browserWin = (BrowserWindow*)[browser window]; - [browserWin setSuppressMakeKeyFront:YES]; // prevent gecko focus bringing the window to the front - [browserWin orderWindow:NSWindowBelow relativeTo:[window windowNumber]]; - [browserWin setSuppressMakeKeyFront:NO]; - } - else - { - [browser showWindow: self]; - } - - // The process of creating a new tab in this brand new window loads about:blank for us as a - // side effect of calling GetDocument(). We don't need to do it again. - if ([MainController isBlankURL:aURL]) - [browser disableLoadPage]; - else - [browser loadURL:aURL referrer:aReferrer focusContent:YES allowPopups:inAllowPopups]; - - return browser; -} - -- (BrowserWindowController*)openBrowserWindowWithURLs:(NSArray*)urlArray behind:(NSWindow*)window allowPopups:(BOOL)inAllowPopups -{ - BrowserWindowController* browser = [[BrowserWindowController alloc] initWithWindowNibName: @"BrowserWindow"]; - - if (window) - { - BrowserWindow* browserWin = (BrowserWindow*)[browser window]; - [browserWin setSuppressMakeKeyFront:YES]; // prevent gecko focus bringing the window to the front - [browserWin orderWindow: NSWindowBelow relativeTo: [window windowNumber]]; - [browserWin setSuppressMakeKeyFront:NO]; - } - else - { - [browser showWindow:self]; - } - - [browser openURLArray:urlArray tabOpenPolicy:eReplaceTabs allowPopups:inAllowPopups]; - return browser; -} - -// open a new URL, observing the prefs on how to behave -- (void)openNewWindowOrTabWithURL:(NSString*)inURLString andReferrer:(NSString*)aReferrer alwaysInFront:(BOOL)forceFront -{ - // make sure we're initted - [PreferenceManager sharedInstance]; - - PRInt32 reuseWindow = 0; - PRBool loadInBackground = PR_FALSE; - - nsCOMPtr prefService ( do_GetService(NS_PREF_CONTRACTID) ); - if ( prefService ) { - prefService->GetIntPref("browser.reuse_window", &reuseWindow); - if (!forceFront) - prefService->GetBoolPref("browser.tabs.loadInBackground", &loadInBackground); - } - - // reuse the main window (if there is one) based on the pref in the - // tabbed browsing panel. The user may have closed all of - // them or we may get this event at startup before we've had time to load - // our window. - BrowserWindowController* controller = (BrowserWindowController*)[[self getFrontmostBrowserWindow] windowController]; - if (controller) { - BOOL tabOrWindowIsAvailable = ([[controller getBrowserWrapper] isEmpty] && ![[controller getBrowserWrapper] isBusy]); - - if (tabOrWindowIsAvailable || reuseWindow == kReuseWindowOnAE) - [controller loadURL:inURLString]; - else if (reuseWindow == kOpenNewTabOnAE) - [controller openNewTabWithURL:inURLString referrer:aReferrer loadInBackground:loadInBackground allowPopups:NO setJumpback:NO]; - else - { - // note that we're opening a new window here - controller = [controller openNewWindowWithURL:inURLString referrer:aReferrer loadInBackground:loadInBackground allowPopups:NO]; - } - if (!loadInBackground) - [[controller window] makeKeyAndOrderFront:nil]; - } - else - controller = [self openBrowserWindowWithURL:inURLString andReferrer:aReferrer behind:nil allowPopups:NO]; -} - -// Bookmarks menu actions. --(IBAction) importBookmarks:(id)aSender -{ - [[BookmarkManager sharedBookmarkManager] startImportBookmarks]; -} - -// helper for exportBookmarks function --(IBAction) setFileExtension:(id)aSender -{ - if ([[aSender title] isEqualToString:@"HTML"]) - [[aSender representedObject] setRequiredFileType:@"html"]; - else - [[aSender representedObject] setRequiredFileType:@"plist"]; -} - --(IBAction) exportBookmarks:(id)aSender -{ - NSSavePanel* savePanel = [NSSavePanel savePanel]; - [savePanel setPrompt:NSLocalizedString(@"Export", @"Export")]; - [savePanel setRequiredFileType:@"html"]; - [savePanel setCanSelectHiddenExtension: YES]; - - // get an accessory view for HTML or Safari .plist output - if (!mExportPanelView) - [NSBundle loadNibNamed:@"AccessoryViews" owner:self]; - NSPopUpButton *button = [mExportPanelView viewWithTag:1001]; - [[button itemAtIndex:0] setRepresentedObject:savePanel]; - [[button itemAtIndex:1] setRepresentedObject:savePanel]; - [savePanel setAccessoryView:mExportPanelView]; - - // start the save panel - int saveResult = [savePanel runModalForDirectory:nil file:NSLocalizedString(@"ExportedBookmarkFile", @"Exported Bookmarks")]; - int selectedButton = [button indexOfSelectedItem]; - if (saveResult != NSFileHandlingPanelOKButton) - return; - if (0 == selectedButton) - [[BookmarkManager sharedBookmarkManager] writeHTMLFile:[savePanel filename]]; - else - [[BookmarkManager sharedBookmarkManager] writeSafariFile:[savePanel filename]]; -} - --(IBAction) openMenuBookmark:(id)aSender -{ - BookmarkItem* item = [aSender representedObject]; - EBookmarkOpenBehavior openBehavior = eBookmarkOpenBehavior_Preferred; - BOOL reverseBackgroundPref = NO; - - if ([aSender isAlternate]) { - reverseBackgroundPref = ([aSender keyEquivalentModifierMask] & NSShiftKeyMask) != 0; - if ([aSender keyEquivalentModifierMask] & NSCommandKeyMask) - openBehavior = eBookmarkOpenBehavior_NewPreferred; - } - // safeguard for bookmark menus that don't have alternates yet - else if ([[NSApp currentEvent] modifierFlags] & NSCommandKeyMask) - openBehavior = eBookmarkOpenBehavior_NewPreferred; - - [self loadBookmark:item withBWC:[self getMainWindowBrowserController] openBehavior:openBehavior reverseBgToggle:reverseBackgroundPref]; -} - -// -// -showHistory: -// -// show the history in the bookmark manager. Creates a new window if -// one isn't already there. history isn't a toggle, hence the name. -// --(IBAction) showHistory:(id)aSender -{ - NSWindow* browserWindow = [self getFrontmostBrowserWindow]; - if (browserWindow) { - if (![browserWindow isMainWindow]) - [browserWindow makeKeyAndOrderFront:self]; - } else { - [self newWindow:self]; - browserWindow = [mApplication mainWindow]; - } - - [[browserWindow windowController] manageHistory: aSender]; -} - -// -// -clearHistory: -// -// clear the global history, after showing a warning -// --(IBAction)clearHistory:(id)aSender -{ - if (NSRunCriticalAlertPanel(NSLocalizedString(@"ClearHistoryTitle", nil), - NSLocalizedString(@"ClearHistoryMessage", nil), - NSLocalizedString(@"ClearHistoryButton", nil), - NSLocalizedString(@"CancelButtonText", nil), - nil) == NSAlertDefaultReturn) - { - // clear history - nsCOMPtr hist = do_GetService("@mozilla.org/browser/global-history;2"); - if (hist) - hist->RemoveAllPages(); - } -} - -// -// manageBookmarks: -// -// toggle the bookmark manager (creating a new window if needed) -// --(IBAction)manageBookmarks:(id)aSender -{ - NSWindow* browserWindow = [self getFrontmostBrowserWindow]; - if (browserWindow) { - if (![browserWindow isMainWindow]) - [browserWindow makeKeyAndOrderFront:self]; - } else { - [self newWindow:self]; - browserWindow = [mApplication mainWindow]; - } - - [[browserWindow windowController] manageBookmarks: aSender]; -} - -- (void)displayPreferencesWindow:(id)sender -{ - [[MVPreferencesController sharedInstance] showPreferences:nil]; -} - -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ - // We can get called before -applicationDidFinishLaunching, so make sure gecko - // has been initted - [self ensureGeckoInitted]; - - NSURL* urlToOpen = [MainController decodeLocalFileURL:[NSURL fileURLWithPath:filename]]; - [self openNewWindowOrTabWithURL:[urlToOpen absoluteString] andReferrer:nil alwaysInFront:YES]; - return YES; -} - -- (IBAction)makeTextBigger:(id)aSender -{ - [[self getMainWindowBrowserController] makeTextBigger:aSender]; -} - -- (IBAction)makeTextSmaller:(id)aSender -{ - [[self getMainWindowBrowserController] makeTextSmaller:aSender]; -} - -- (IBAction)makeTextDefaultSize:(id)aSender -{ - [[self getMainWindowBrowserController] makeTextDefaultSize:aSender]; -} - --(IBAction) viewSource:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - [browserController viewPageSource: aSender]; // top-level page, not focussed frame -} - --(BOOL)isMainWindowABrowserWindow -{ - // see also getFrontmostBrowserWindow. That will always return a browser - // window if one exists. This will only return one if it is frontmost. - return [[[mApplication mainWindow] windowController] isMemberOfClass:[BrowserWindowController class]]; -} - -- (BrowserWindowController*)getMainWindowBrowserController -{ - // note that [NSApp mainWindow] will return NULL if we are not - // frontmost - NSWindowController* mainWindowController = [[mApplication mainWindow] windowController]; - if (mainWindowController && [mainWindowController isMemberOfClass:[BrowserWindowController class]]) - return (BrowserWindowController*)mainWindowController; - - return nil; -} - -- (BrowserWindowController*)getKeyWindowBrowserController -{ - NSWindowController* keyWindowController = [[mApplication keyWindow] windowController]; - if (keyWindowController && [keyWindowController isMemberOfClass:[BrowserWindowController class]]) - return (BrowserWindowController*)keyWindowController; - - return nil; -} - - (void)adjustCloseWindowMenuItemKeyEquivalent:(BOOL)inHaveTabs { // capitalization of the key equivalent affects whether the shift modifer is used. - [mCloseWindowMenuItem setKeyEquivalent: inHaveTabs ? @"W" : @"w"]; + [mCloseWindowMenuItem setKeyEquivalent:(inHaveTabs ? @"W" : @"w")]; } - (void)adjustCloseTabMenuItemKeyEquivalent:(BOOL)inHaveTabs @@ -1400,10 +1727,9 @@ Otherwise, we return the URL we originally got. Right now this supports .url, - (void)delayedFixCloseMenuItemKeyEquivalents { - // we do this after a delay to ensure that window layer state has been set by the time - // we do the enabling. - if (!mFileMenuUpdatePending) - { + // we do this after a delay to ensure that window layer state has been set by the time + // we do the enabling. + if (!mFileMenuUpdatePending) { [self performSelector:@selector(fixCloseMenuItemKeyEquivalents) withObject:nil afterDelay:0]; mFileMenuUpdatePending = YES; } @@ -1414,470 +1740,39 @@ Otherwise, we return the URL we originally got. Right now this supports .url, - (void)fixCloseMenuItemKeyEquivalents { BrowserWindowController* browserController = [self getKeyWindowBrowserController]; - BOOL windowWithMultipleTabs = (browserController && [[browserController getTabBrowser] numberOfTabViewItems] > 1); + BOOL windowWithMultipleTabs = (browserController && [[browserController getTabBrowser] numberOfTabViewItems] > 1); [self adjustCloseWindowMenuItemKeyEquivalent:windowWithMultipleTabs]; [self adjustCloseTabMenuItemKeyEquivalent:windowWithMultipleTabs]; mFileMenuUpdatePending = NO; } -- (void)delayedUpdatePageInfo +- (NSMenu*)applicationDockMenu:(NSApplication*)sender { - if (!mPageInfoUpdatePending) - { - [self performSelector:@selector(updatePageInfo) withObject:nil afterDelay:0]; - mPageInfoUpdatePending = YES; - } + // The OS check is needed because 10.3 can't handle alternates in dock menus. Remove it (and the |withAlternates| params + // that exist to deal with it) once we're 10.4+ + BOOL isTigerOrHigher = [NSWorkspace isTigerOrHigher]; + + // the dock menu doesn't get the usual show notifications, so we rebuild it explicitly here + [mDockMenu rebuildMenuIncludingSubmenus:YES withAlternates:isTigerOrHigher]; + return mDockMenu; } -- (void)updatePageInfo +- (void)dockMenuBookmarkFolderChanged:(NSNotification*)inNotification { - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - [[PageInfoWindowController visiblePageInfoWindowController] updateFromBrowserView:[browserController activeBrowserView]]; - mPageInfoUpdatePending = NO; + [self updateDockMenuBookmarkFolder]; } -- (void)adjustTextEncodingMenu +- (void)updateDockMenuBookmarkFolder { - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (browserController) - { - // enable all items - [mTextEncodingsMenu setAllItemsEnabled:YES startingWithItemAtIndex:0 includingSubmenus:YES]; - - NSString* charset = [browserController currentCharset]; -#if DEBUG_CHARSET - NSLog(@"charset is %@", charset); -#endif - NSNumber* tag = [mCharsets objectForKey:[charset lowercaseString]]; - [mTextEncodingsMenu checkItemWithTag:[tag intValue] uncheckingOtherItems:YES]; - } - else - { - [mTextEncodingsMenu setAllItemsEnabled:NO startingWithItemAtIndex:0 includingSubmenus:YES]; - // always enable the autodetect item - [[mTextEncodingsMenu itemWithTag:kEncodingMenuAutodetectItemTag] setEnabled:YES]; - } - - // update the state of the autodetect item - NSString* detectorValue = [[PreferenceManager sharedInstance] getStringPref:"intl.charset.detector" withSuccess:NULL]; - BOOL universalChardetOn = [detectorValue isEqualToString:@"universal_charset_detector"]; - [[mTextEncodingsMenu itemWithTag:kEncodingMenuAutodetectItemTag] setState:universalChardetOn ? NSOnState : NSOffState]; + [mDockMenu setBookmarkFolder:[[BookmarkManager sharedBookmarkManager] dockMenuFolder]]; } --(BOOL)validateMenuItem:(NSMenuItem*)aMenuItem -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - SEL action = [aMenuItem action]; - - // NSLog(@"MainController validateMenuItem for %@ (%s)", [aMenuItem title], action); - - // disable items that aren't relevant if there's no main browser window open - // or the bookmark/history manager is open - // XXX some of these should be wired to the First Responder (like reload:). - if (action == @selector(printPage:) || - /* ... many more items go here ... */ - action == @selector(pageSetup:) || - action == @selector(findInPage:) || - action == @selector(savePage:)) - { - return (browserController && ![browserController bookmarkManagerIsVisible]); - } - - if (action == @selector(doReload:)) - return (browserController && [[browserController getBrowserWrapper] canReload]); - - if (action == @selector(doReloadAllTabs:)) - return (browserController != nil); - - // disable open menu items if a sheet is up (maybe disable others too) - if (action == @selector(openFile:) || - action == @selector(openLocation:)) { - return (!browserController || [[browserController window] attachedSheet] == nil); - } - - // check what the state of the personal toolbar should be, but only if there is a browser - // window open. Popup windows that have the personal toolbar removed should always gray - // out this menu. - if (action == @selector(toggleBookmarksToolbar:)) { - if (browserController) { - NSView* bookmarkToolbar = [browserController bookmarkToolbar]; - if ( bookmarkToolbar ) { - float height = [bookmarkToolbar frame].size.height; - BOOL toolbarShowing = (height > 0); - if (toolbarShowing) - [mBookmarksToolbarMenuItem setTitle: NSLocalizedString(@"Hide Bookmarks Toolbar",@"")]; - else - [mBookmarksToolbarMenuItem setTitle: NSLocalizedString(@"Show Bookmarks Toolbar",@"")]; - return YES; - } - } - return NO; - } - - // only enable newTab if there is a browser window frontmost, or if there is no window - // (i.e. disable it for non-browser windows). - if (action == @selector(newTab:)) - { - return (browserController || ![NSApp mainWindow]); - } - - if (action == @selector(closeTab:)) - { - BrowserWindowController* keyBWC = [self getKeyWindowBrowserController]; - return (keyBWC && [[keyBWC getTabBrowser] numberOfTabViewItems] > 1); - } - - // only activate if we've got multiple tabs open. - if (action == @selector(nextTab:) || - action == @selector(previousTab:)) - { - return (browserController && [[browserController getTabBrowser] numberOfTabViewItems] > 1); - } - - if (action == @selector(makeTextBigger:)) - return (browserController && [browserController canMakeTextBigger]); - - if (action == @selector(makeTextSmaller:)) - return (browserController && [browserController canMakeTextSmaller]); - - if (action == @selector(makeTextDefaultSize:)) - return (browserController && [browserController canMakeTextDefaultSize]); - - // don't allow View Source on the bookmark manager or on non-text content - if (action == @selector(viewSource:)) { - return (browserController && - ![browserController bookmarkManagerIsVisible] && - [[[browserController getBrowserWrapper] getBrowserView] isTextBasedContent]); - } - - if (action == @selector(doStop:)) - return (browserController && [[browserController getBrowserWrapper] isBusy]); - - if (action == @selector(goBack:) || action == @selector(goForward:)) { - if (browserController) { - CHBrowserView* browserView = [[browserController getBrowserWrapper] getBrowserView]; - if (action == @selector(goBack:)) - return [browserView canGoBack]; - if (action == @selector(goForward:)) - return [browserView canGoForward]; - } - return NO; - } - - if (action == @selector(manageBookmarks:)) - { - BOOL showingBookmarks = (browserController && [browserController bookmarkManagerIsVisible]); - NSString* showBMLabel = showingBookmarks ? NSLocalizedString(@"Hide All Bookmarks", @"") - : NSLocalizedString(@"Show All Bookmarks", @""); - [aMenuItem setTitle:showBMLabel]; - return showingBookmarks ? [browserController canHideBookmarks] : YES; - } - - if (action == @selector(sendURL:)) - return ![[[browserController getBrowserWrapper] getCurrentURI] hasPrefix:@"about:"]; - - // key alternates - if (action == @selector(openMenuBookmark:) && [aMenuItem isAlternate]) { - if ([[PreferenceManager sharedInstance] getBooleanPref:"browser.tabs.opentabfor.middleclick" withSuccess:NULL]) - [aMenuItem setTitle:NSLocalizedString(@"Open in New Tabs", nil)]; - else - [aMenuItem setTitle:NSLocalizedString(@"Open in Tabs in New Window", nil)]; - } - - // default return - return YES; -} - --(IBAction) toggleBookmarksToolbar:(id)aSender -{ - BrowserWindowController* browserController = [self getMainWindowBrowserController]; - if (!browserController) return; - - float height = [[browserController bookmarkToolbar] frame].size.height; - BOOL showToolbar = (BOOL)(!(height > 0)); - - [[browserController bookmarkToolbar] showBookmarksToolbar: showToolbar]; - - // save prefs here - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - [defaults setInteger: ((showToolbar) ? 0 : 1) forKey: USER_DEFAULTS_HIDE_PERS_TOOLBAR_KEY]; -} - --(IBAction) zoomAll:(id)aSender -{ - NSArray* windows = [NSApp windows]; - NSEnumerator* windowEnum = [windows objectEnumerator]; - NSWindow* curWindow; - - while (curWindow = [windowEnum nextObject]) - if ([[curWindow windowController] isMemberOfClass:[BrowserWindowController class]]) - [curWindow zoom:aSender]; -} - --(IBAction) supportLink:(id)aSender; -{ - NSString* pageToLoad = NSLocalizedStringFromTable(@"SupportPageDefault", @"WebsiteDefaults", nil); - if (![pageToLoad isEqualToString:@"SupportPageDefault"]) - [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; -} - --(IBAction) infoLink:(id)aSender -{ - NSString* pageToLoad = NSLocalizedStringFromTable(@"InfoPageDefault", @"WebsiteDefaults", nil); - if (![pageToLoad isEqualToString:@"InfoPageDefault"]) - [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; -} - --(IBAction) feedbackLink:(id)aSender -{ - NSString *pageToLoad = NSLocalizedStringFromTable(@"FeedbackPageDefault", @"WebsiteDefaults", nil); - if (![pageToLoad isEqualToString:@"FeedbackPageDefault"]) - [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; -} - --(IBAction) releaseNoteLink:(id)aSender -{ - NSString *pageToLoad = NSLocalizedStringFromTable(@"ReleaseNotesDefault", @"WebsiteDefaults", nil); - if (![pageToLoad isEqualToString:@"ReleaseNotesDefault"]) - [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; -} - --(IBAction) tipsTricksLink:(id)aSender -{ - NSString *pageToLoad = NSLocalizedStringFromTable(@"TipsTricksPageDefault", @"WebsiteDefaults", nil); - if (![pageToLoad isEqualToString:@"TipsTricksPageDefault"]) - [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; -} - --(IBAction) searchCustomizeLink:(id)aSender -{ - NSString *pageToLoad = NSLocalizedStringFromTable(@"SearchCustomPageDefault", @"WebsiteDefaults", nil); - if (![pageToLoad isEqualToString:@"SearchCustomPageDefault"]) - [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; -} - --(IBAction) aboutPlugins:(id)aSender -{ - [self openNewWindowOrTabWithURL:@"about:plugins" andReferrer:nil alwaysInFront:YES]; -} - -- (IBAction)showCertificates:(id)aSender -{ - [[CertificatesWindowController sharedCertificatesWindowController] showWindow:nil]; -} - -- (void)showCertificatesNotification:(NSNotification*)inNotification -{ - [self showCertificates:nil]; -} - -+ (NSImage*)createImageForDragging:(NSImage*)aIcon title:(NSString*)aTitle -{ - const float kTitleOffset = 2.0f; - - NSDictionary* stringAttrs = [NSDictionary dictionaryWithObjectsAndKeys: - [[NSColor textColor] colorWithAlphaComponent:0.8], NSForegroundColorAttributeName, - [NSFont systemFontOfSize:[NSFont smallSystemFontSize]], NSFontAttributeName, - nil]; - - // get the size of the new image we are creating - NSSize titleSize = [aTitle sizeWithAttributes:stringAttrs]; - NSSize imageSize = NSMakeSize(titleSize.width + [aIcon size].width + kTitleOffset + 2, - titleSize.height > [aIcon size].height ? - titleSize.height : [aIcon size].height); - - // create the image and lock drawing focus on it - NSImage* dragImage = [[[NSImage alloc] initWithSize:imageSize] autorelease]; - [dragImage lockFocus]; - - // draw the image and title in image with translucency - NSRect imageRect = NSMakeRect(0, 0, [aIcon size].width, [aIcon size].height); - [aIcon drawAtPoint:NSMakePoint(0, 0) fromRect:imageRect operation:NSCompositeCopy fraction:0.8]; - - [aTitle drawAtPoint:NSMakePoint([aIcon size].width + kTitleOffset, 0.0) withAttributes:stringAttrs]; - - [dragImage unlockFocus]; - return dragImage; -} - -- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApp hasVisibleWindows:(BOOL)flag -{ - // we might be sitting there with the "there is another copy of camino running" dialog up - // (which means we're in a modal loop in [PreferenceManager init]). So if we haven't - // finished initting prefs yet, just bail. - if (![PreferenceManager sharedInstanceDontCreate]) - return NO; - - // ignore |hasVisibleWindows| because we always want to show a browser window when - // the user clicks on the app icon, even if, say, prefs or the d/l window are open. - // If there is no browser, create one. If there is one, unminimize it if it's in the dock. - NSWindow* frontBrowser = [self getFrontmostBrowserWindow]; - if ( !frontBrowser ) - [self newWindow:self]; - else if ([frontBrowser isMiniaturized]) - [frontBrowser deminiaturize:self]; - - return NO; -} - -- (void) applicationDidChangeScreenParameters:(NSNotification *)aNotification -{ - [NSApp makeWindowsPerform:@selector(display) inOrder:YES]; -} - -- (void)applicationDidBecomeActive:(NSNotification *)aNotification -{ - [mFindDialog applicationWasActivated]; -} - -// -// -aboutWindow: -// -// Show the (slightly modified) standard about window, with the build id instead of the -// typical application version. It'll display like "2003120403 (v0.7+)". -// --(IBAction)aboutWindow:(id)sender -{ - NSString* version = [NSString stringWithFormat:@"%010u", NS_BUILD_ID]; - NSDictionary* d = [NSDictionary dictionaryWithObject:version forKey:@"ApplicationVersion"]; - [NSApp orderFrontStandardAboutPanelWithOptions:d]; -} - -// services - -- (void)openURL:(NSPasteboard *) pboard userData:(NSString *) userData error:(NSString **) error -{ - NSArray* types = [pboard types]; - if (![types containsObject:NSStringPboardType]) { - *error = NSLocalizedString(@"Error: couldn't open URL.", - @"pboard couldn't give URL string."); - return; - } - NSString* urlString = [pboard stringForType:NSStringPboardType]; - if (!urlString) { - *error = NSLocalizedString(@"Error: couldn't open URL.", - @"pboard couldn't give URL string."); - return; - } - - // check to see if it's a bookmark keyword - NSArray *resolvedURLs = [[BookmarkManager sharedBookmarkManager] resolveBookmarksKeyword:urlString]; - - if (resolvedURLs) { - if ([resolvedURLs count] == 1) - [self openNewWindowOrTabWithURL:[resolvedURLs lastObject] andReferrer:nil alwaysInFront:YES]; - else - [self openBrowserWindowWithURLs:resolvedURLs behind:nil allowPopups:NO]; - } - else { - urlString = [urlString stringByRemovingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; - [self openNewWindowOrTabWithURL:urlString andReferrer:nil alwaysInFront:YES]; - } -} - -// -// -emptyCache: -// -// Puts up a modal panel and if the user gives the go-ahead, emtpies the disk and memory -// caches. We keep this separate from |-resetBrowser:| so the user can just clear the cache -// and not have to delete everything (such as their keychain passwords). -// -- (IBAction)emptyCache:(id)sender -{ - if (NSRunCriticalAlertPanel(NSLocalizedString(@"EmptyCacheTitle", nil), - NSLocalizedString(@"EmptyCacheMessage", nil), - NSLocalizedString(@"EmptyButton", nil), - NSLocalizedString(@"CancelButtonText", nil), nil) == NSAlertDefaultReturn) - { - // remove cache - nsCOMPtr cacheServ (do_GetService("@mozilla.org/network/cache-service;1")); - if (cacheServ) - cacheServ->EvictEntries(nsICache::STORE_ANYWHERE); - } -} - -// -// -resetBrowser: -// -// Here we need to: -// - warn user about what is going to happen -// - if its OK... -// - close all open windows, delete cache, history, cookies, site permissions, -// downloads, saved names and passwords, and clear Top 10 group in bookmarks -// -- (IBAction)resetBrowser:(id)sender -{ - if (NSRunCriticalAlertPanel(NSLocalizedString(@"Reset Camino Title", nil), - NSLocalizedString(@"Reset Warning Message", nil), - NSLocalizedString(@"Reset Camino", nil), - NSLocalizedString(@"CancelButtonText", nil), - nil) == NSAlertDefaultReturn) - { - - // close all windows - { - NSArray* openWindows = [[NSApp orderedWindows] copy]; - NSEnumerator* windowEnum = [openWindows objectEnumerator]; - NSWindow* curWindow; - while ((curWindow = [windowEnum nextObject])) - { - // we don't want the "you are closing a window with multiple tabs" warning to show up. - if ([[curWindow windowController] isMemberOfClass:[BrowserWindowController class]]) - [(BrowserWindowController*)[curWindow windowController] setWindowClosesQuietly:YES]; - - if ([curWindow isVisible] || [curWindow isMiniaturized]) - [curWindow performClose:self]; - } - [openWindows release]; - } - - // remove cache - nsCOMPtr cacheServ (do_GetService("@mozilla.org/network/cache-service;1")); - if (cacheServ) - cacheServ->EvictEntries(nsICache::STORE_ANYWHERE); - - // remove cookies - nsCOMPtr cm(do_GetService(NS_COOKIEMANAGER_CONTRACTID)); - nsICookieManager* mCookieManager = cm.get(); - if (mCookieManager) - mCookieManager->RemoveAll(); - - // remove site permissions - nsCOMPtr pm(do_GetService(NS_PERMISSIONMANAGER_CONTRACTID)); - nsIPermissionManager* mPermissionManager = pm.get(); - if (mPermissionManager) - mPermissionManager->RemoveAll(); - - // remove history - nsCOMPtr hist (do_GetService("@mozilla.org/browser/global-history;2")); - if (hist) - hist->RemoveAllPages(); - - // remove downloads - [[ProgressDlgController sharedDownloadController] clearAllDownloads]; - -#if 0 // disable this for now (see bug 3202080> - // remove saved names and passwords - [[KeychainService instance] removeAllUsernamesAndPasswords]; -#endif - - // re-set all bookmarks visit counts to zero - [[BookmarkManager sharedBookmarkManager] clearAllVisits]; - - // open a new window - [self newWindow:self]; - } -} - -#pragma mark - - - -static int SortByProtocolAndName(NSDictionary* item1, NSDictionary* item2, void *context) +static int SortByProtocolAndName(NSDictionary* item1, NSDictionary* item2, void* context) { NSComparisonResult protocolCompare = [[item1 objectForKey:@"name"] compare:[item2 objectForKey:@"name"] options:NSCaseInsensitiveSearch]; if (protocolCompare != NSOrderedSame) return protocolCompare; - + return [[item1 objectForKey:@"protocol"] compare:[item2 objectForKey:@"protocol"] options:NSCaseInsensitiveSearch]; } @@ -1885,13 +1780,13 @@ static int SortByProtocolAndName(NSDictionary* item1, NSDictionary* item2, void // NetworkServicesClient implementation // XXX maybe just use the bookmarks smart folder for this menu? // -- (void)availableServicesChanged:(NSNotification *)note +- (void)availableServicesChanged:(NSNotification*)note { // rebuild the submenu, leaving the first item while ([mServersSubmenu numberOfItems] > 1) [mServersSubmenu removeItemAtIndex:[mServersSubmenu numberOfItems] - 1]; - NetworkServices *netserv = [note object]; + NetworkServices* netserv = [note object]; NSEnumerator* keysEnumerator = [netserv serviceEnumerator]; // build an array of dictionaries, so we can sort it @@ -1919,15 +1814,15 @@ static int SortByProtocolAndName(NSDictionary* item1, NSDictionary* item2, void else { // add a separator [mServersSubmenu addItem:[NSMenuItem separatorItem]]; - + // sort on protocol, then name [servicesArray sortUsingFunction:SortByProtocolAndName context:NULL]; - + unsigned count = [servicesArray count]; for (unsigned int i = 0; i < count; i++) { NSDictionary* serviceDict = [servicesArray objectAtIndex:i]; NSString* itemName = [[serviceDict objectForKey:@"name"] stringByAppendingString:NSLocalizedString([serviceDict objectForKey:@"protocol"], @"")]; - + id newItem = [mServersSubmenu addItemWithTitle:itemName action:@selector(connectToServer:) keyEquivalent:@""]; [newItem setTag:[[serviceDict objectForKey:@"id"] intValue]]; [newItem setTarget:self]; @@ -1937,9 +1832,9 @@ static int SortByProtocolAndName(NSDictionary* item1, NSDictionary* item2, void [servicesArray release]; } -- (void)serviceResolved:(NSNotification *)note +- (void)serviceResolved:(NSNotification*)note { - NSDictionary *dict = [note userInfo]; + NSDictionary* dict = [note userInfo]; if ([dict objectForKey:NetworkServicesClientKey] == self) [self openNewWindowOrTabWithURL:[dict objectForKey:NetworkServicesResolvedURLKey] andReferrer:nil alwaysInFront:YES]; } @@ -1947,9 +1842,9 @@ static int SortByProtocolAndName(NSDictionary* item1, NSDictionary* item2, void // // handles resolution failure for everybody else // -- (void)serviceResolutionFailed:(NSNotification *)note +- (void)serviceResolutionFailed:(NSNotification*)note { - NSDictionary *dict = [note userInfo]; + NSDictionary* dict = [note userInfo]; NSString* serviceName = [dict objectForKey:NetworkServicesServiceKey]; NSBeginAlertSheet(NSLocalizedString(@"ServiceResolutionFailedTitle", @""), @"", // default button @@ -1964,16 +1859,111 @@ static int SortByProtocolAndName(NSDictionary* item1, NSDictionary* item2, void ); } --(IBAction) connectToServer:(id)aSender +#pragma mark - +#pragma mark Supplemental View Helpers + +- (NSView*)getSavePanelView { - [[NetworkServices sharedNetworkServices] attemptResolveService:[aSender tag] forSender:self]; + if (!mFilterView) { + // note that this will cause our -awakeFromNib to get called again + [NSBundle loadNibNamed:@"AccessoryViews" owner:self]; + } + return mFilterView; } --(IBAction) aboutServers:(id)aSender +- (void)delayedUpdatePageInfo { - NSString *pageToLoad = NSLocalizedStringFromTable(@"RendezvousPageDefault", @"WebsiteDefaults", nil); - if (![pageToLoad isEqualToString:@"RendezvousPageDefault"]) - [self openNewWindowOrTabWithURL:pageToLoad andReferrer:nil alwaysInFront:YES]; + if (!mPageInfoUpdatePending) { + [self performSelector:@selector(updatePageInfo) withObject:nil afterDelay:0]; + mPageInfoUpdatePending = YES; + } +} + +- (void)updatePageInfo +{ + BrowserWindowController* browserController = [self getMainWindowBrowserController]; + [[PageInfoWindowController visiblePageInfoWindowController] updateFromBrowserView:[browserController activeBrowserView]]; + mPageInfoUpdatePending = NO; +} + +- (IBAction)showCertificates:(id)aSender +{ + [[CertificatesWindowController sharedCertificatesWindowController] showWindow:nil]; +} + +- (void)showCertificatesNotification:(NSNotification*)inNotification +{ + [self showCertificates:nil]; +} + +// helper for exportBookmarks function +- (IBAction)setFileExtension:(id)aSender +{ + if ([[aSender title] isEqualToString:@"HTML"]) + [[aSender representedObject] setRequiredFileType:@"html"]; + else + [[aSender representedObject] setRequiredFileType:@"plist"]; +} + +#pragma mark - +#pragma mark Miscellaneous Utilities +//which may not belong in MainController at all + +// +// This takes an NSURL to a local file, and if that file is a file that contains +// a URL we want and isn't the content itself, we return the URL it contains. +// Otherwise, we return the URL we originally got. Right now this supports .url, +// .webloc and .ftploc files. +// ++ (NSURL*)decodeLocalFileURL:(NSURL*)url +{ + NSString* urlPathString = [url path]; + NSString* ext = [[urlPathString pathExtension] lowercaseString]; + OSType fileType = NSHFSTypeCodeFromFileType(NSHFSTypeOfFile(urlPathString)); + + if ([ext isEqualToString:@"url"] || fileType == 'LINK') + url = [NSURL URLFromIEURLFile:urlPathString]; + else if ([ext isEqualToString:@"webloc"] || [ext isEqualToString:@"ftploc"] || fileType == 'ilht' || fileType == 'ilft') + url = [NSURL URLFromInetloc:urlPathString]; + + return url; +} + ++ (NSImage*)createImageForDragging:(NSImage*)aIcon title:(NSString*)aTitle +{ + const float kTitleOffset = 2.0f; + + NSDictionary* stringAttrs = [NSDictionary dictionaryWithObjectsAndKeys: + [[NSColor textColor] colorWithAlphaComponent:0.8], NSForegroundColorAttributeName, + [NSFont systemFontOfSize:[NSFont smallSystemFontSize]], NSFontAttributeName, + nil]; + + // get the size of the new image we are creating + NSSize titleSize = [aTitle sizeWithAttributes:stringAttrs]; + NSSize imageSize = NSMakeSize(titleSize.width + [aIcon size].width + kTitleOffset + 2, + titleSize.height > [aIcon size].height ? titleSize.height + : [aIcon size].height); + + // create the image and lock drawing focus on it + NSImage* dragImage = [[[NSImage alloc] initWithSize:imageSize] autorelease]; + [dragImage lockFocus]; + + // draw the image and title in image with translucency + NSRect imageRect = NSMakeRect(0, 0, [aIcon size].width, [aIcon size].height); + [aIcon drawAtPoint:NSMakePoint(0, 0) fromRect:imageRect operation:NSCompositeCopy fraction:0.8]; + + [aTitle drawAtPoint:NSMakePoint([aIcon size].width + kTitleOffset, 0.0) withAttributes:stringAttrs]; + + [dragImage unlockFocus]; + return dragImage; +} + ++ (BOOL)isBlankURL:(NSString*)inURL +{ + BOOL isBlank = NO; + if (!inURL || [inURL isEqualToString:@"about:blank"] || [inURL isEqualToString:@""]) + isBlank = YES; + return isBlank; } @end