Changes for bug 160725: adding site icon support to the proxy icon, tabs, bookmarks (in sidebar, tolbar and menu). Site icons are fetched via the SiteIconProvider, which uses the more generic RemoteDataProvider under the hood. RemoteDataProvider talks to necko, getting the resulting data into an NSData. Notifications are used to indicate to listeners when the load is done.

Site icons that are loaded to into the necko cache. We also cache data for missing site icons, to avoid continual refetches.

Site icons are on by default, but can be turned off via the "browser.chrome.site_icons" pref.
This commit is contained in:
sfraser%netscape.com 2002-08-15 18:08:12 +00:00
Родитель c6fde33f13
Коммит 3e9dcd40e5
96 изменённых файлов: 5680 добавлений и 1004 удалений

Просмотреть файл

@ -49,6 +49,7 @@ class BookmarksService;
@class BookmarkInfoController;
// data source for the bookmarks sidebar. We make one per browser window.
@interface BookmarksDataSource : NSObject
{
BookmarksService* mBookmarks;
@ -106,14 +107,16 @@ class BookmarksService;
@interface BookmarkItem : NSObject
{
nsIContent* mContentNode;
NSImage* mSiteIcon;
}
- (nsIContent*)contentNode;
- (void)setContentNode: (nsIContent*)aContentNode;
- (void)setSiteIcon:(NSImage*)image;
- (NSString*)url;
- (NSImage*)siteIcon;
- (NSNumber*)contentID;
- (id)copyWithZone:(NSZone *)aZone;
- (BOOL)isFolder;
@end

Просмотреть файл

@ -41,6 +41,7 @@
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "SiteIconProvider.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
@ -55,17 +56,16 @@
#include "nsVoidArray.h"
#import "BookmarksService.h"
#import "StringUtils.h"
@implementation BookmarksDataSource
-(id) init
{
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
}
-(void) awakeFromNib
@ -86,16 +86,16 @@
-(void) ensureBookmarks
{
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
}
-(IBAction)addBookmark:(id)aSender
@ -530,20 +530,10 @@
//Get the cell of the text attachment.
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
//Figure out which image to add, and set the cell's image.
// Use the bookmark groups image for groups.
if ([self outlineView:outlineView isItemExpandable:item]) {
nsIContent* content = [item contentNode];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, BookmarksService::gGroupAtom, group);
if (!group.IsEmpty())
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"groupbookmark"]];
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]];
}
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
NSImage* bookmarkImage = mBookmarks->CreateIconForBookmark(elt);
[attachmentAttrStringCell setImage:bookmarkImage];
//Insert the image
[cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString];
@ -855,7 +845,16 @@
@end
#pragma mark -
@implementation BookmarkItem
-(void)dealloc
{
[mSiteIcon release];
[super dealloc];
}
-(nsIContent*)contentNode
{
return mContentNode;
@ -887,6 +886,18 @@
return [NSString stringWith_nsAString: href];
}
- (void)setSiteIcon:(NSImage*)image
{
//NSLog(@"Setting site icon for %@", [self url]);
[mSiteIcon autorelease];
mSiteIcon = [image retain];
}
- (NSImage*)siteIcon
{
return mSiteIcon;
}
-(void)setContentNode: (nsIContent*)aContentNode
{
mContentNode = aContentNode;
@ -896,6 +907,7 @@
{
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
[copy setContentNode: mContentNode];
[copy setSiteIcon: mSiteIcon];
return copy;
}

Просмотреть файл

@ -53,6 +53,9 @@ class nsIDOMHTMLDocument;
@class BookmarksDataSource;
@class BookmarkItem;
// despite appearances, BookmarksService is not a singleton. We make one for the bookmarks menu,
// one each per BookmarksDataSource, and one per bookmarks toolbar. It relies on a bunch of global
// variables, which is evil.
class BookmarksService
{
public:
@ -63,6 +66,7 @@ public:
void AddObserver();
void RemoveObserver();
public:
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
@ -71,7 +75,6 @@ public:
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
static void DeleteBookmark(nsIDOMElement* aBookmark);
public:
static void GetRootContent(nsIContent** aResult);
static BookmarkItem* GetRootItem();
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
@ -87,6 +90,8 @@ public:
static void ConstructAddBookmarkFolderList(NSPopUpButton* aPopup, BookmarkItem* aItem);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static void EnsureToolbarRoot();
static void ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc);
@ -96,8 +101,6 @@ public:
static NSString* ResolveKeyword(NSString* aKeyword);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
@ -139,3 +142,23 @@ private:
CHBookmarksToolbar* mToolbar;
BookmarksDataSource* mDataSource;
};
// singleton bookmarks manager object
@interface BookmarksManager : NSObject
{
}
+ (BookmarksManager*)sharedBookmarksManager;
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString;
@end

Просмотреть файл

@ -37,12 +37,13 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserView.h"
#import "BookmarksService.h"
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "CHIconTabViewItem.h"
#import "StringUtils.h"
#import "SiteIconProvider.h"
#include "nsCRT.h"
#include "nsString.h"
@ -106,6 +107,7 @@ NSMutableDictionary* BookmarksService::gDictionary = nil;
MainController* BookmarksService::gMainController = nil;
NSMenu* BookmarksService::gBookmarksMenu = nil;
nsIDOMElement* BookmarksService::gToolbarRoot = nsnull;
nsIAtom* BookmarksService::gBookmarkAtom = nsnull;
nsIAtom* BookmarksService::gDescriptionAtom = nsnull;
nsIAtom* BookmarksService::gFolderAtom = nsnull;
@ -114,8 +116,11 @@ nsIAtom* BookmarksService::gHrefAtom = nsnull;
nsIAtom* BookmarksService::gKeywordAtom = nsnull;
nsIAtom* BookmarksService::gNameAtom = nsnull;
nsIAtom* BookmarksService::gOpenAtom = nsnull;
nsVoidArray* BookmarksService::gInstances = nsnull;
BOOL BookmarksService::gBookmarksFileReadOK = NO;
int BookmarksService::CHInsertNone = 0;
int BookmarksService::CHInsertInto = 1;
int BookmarksService::CHInsertBefore = 2;
@ -137,6 +142,54 @@ BookmarksService::~BookmarksService()
{
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
#pragma mark -
void
BookmarksService::GetRootContent(nsIContent** aResult)
{
@ -211,7 +264,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
}
void
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -258,7 +311,7 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool
}
void
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -289,6 +342,10 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
aItem->GetAttr(kNameSpaceID_None, gNameAtom, name);
NSString* bookmarkTitle = [[NSString stringWith_nsAString: name] stringByTruncatingTo:80 at:kTruncateAtMiddle];
[childItem setTitle: bookmarkTitle];
// and reset the image
BookmarkItem* item = GetWrapperFor(aItem);
[childItem setImage: [item siteIcon]];
}
}
@ -298,7 +355,7 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
}
void
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances)
return;
@ -343,51 +400,6 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bo
FlushBookmarks();
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
void
BookmarksService::AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt)
@ -601,6 +613,40 @@ BookmarksService::FlushBookmarks()
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"groupbookmark"];
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
// fire off a proxy icon load
if ([[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL])
{
nsAutoString href;
content->GetAttr(kNameSpaceID_None, gHrefAtom, href);
if (href.Length() > 0)
{
BookmarkItem* contentItem = BookmarksService::GetWrapperFor(content);
if ([contentItem siteIcon])
return [contentItem siteIcon];
if (contentItem && ![contentItem siteIcon])
[[BookmarksManager sharedBookmarksManager] loadProxyImageFor:contentItem withURI:[NSString stringWith_nsAString:href]];
}
}
return [NSImage imageNamed:@"smallbookmark"];
}
void BookmarksService::EnsureToolbarRoot()
{
if (gToolbarRoot)
@ -763,18 +809,21 @@ BookmarksService::AddMenuBookmark(NSMenu* aMenu, nsIContent* aParent, nsIContent
nsAutoString group;
aChild->GetAttr(kNameSpaceID_None, gGroupAtom, group);
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aChild));
NSImage* menuItemImage = BookmarksService::CreateIconForBookmark(elt);
if (group.IsEmpty() && tagName == gFolderAtom) {
NSMenu* menu = [[[NSMenu alloc] initWithTitle: title] autorelease];
[aMenu setSubmenu: menu forItem: menuItem];
[menu setAutoenablesItems: NO];
[menuItem setImage: [NSImage imageNamed:@"folder"]];
[menuItem setImage: menuItemImage];
ConstructBookmarksMenu(menu, aChild);
}
else {
if (group.IsEmpty())
[menuItem setImage: [NSImage imageNamed:@"smallbookmark"]];
[menuItem setImage: menuItemImage];
else
[menuItem setImage: [NSImage imageNamed:@"groupbookmark"]];
[menuItem setImage: menuItemImage];
[menuItem setTarget: gMainController];
[menuItem setAction: @selector(openMenuBookmark:)];
@ -997,10 +1046,12 @@ BookmarksService::ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc)
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(bookmarksRoot));
nsCOMPtr<nsIContent> childContent(do_QueryInterface(importedRootElement));
#if 0
// XXX testing
if (gDictionary)
[gDictionary removeAllObjects];
#endif
// this will save the file
BookmarkAdded(parentContent, childContent, true /* flush */);
}
@ -1072,24 +1123,7 @@ BookmarksService::ResolveKeyword(NSString* aKeyword)
content->GetAttr(kNameSpaceID_None, gHrefAtom, url);
return [NSString stringWith_nsAString: url];
}
return [NSString stringWithCString:""];
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"smallgroup"];
return [NSImage imageNamed:@"groupbookmark"];
return [NSString string];
}
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
@ -1292,3 +1326,78 @@ BookmarksService::PerformURLDrop(BookmarkItem* parentItem, BookmarkItem* beforeI
return YES;
}
#pragma mark -
@interface BookmarksManager(Private)
- (void)registerNotificationListener;
- (void)imageLoadedNotification:(NSNotification*)notification;
@end
@implementation BookmarksManager
+ (BookmarksManager*)sharedBookmarksManager;
{
static BookmarksManager* sBookmarksManager = nil;
if (!sBookmarksManager)
sBookmarksManager = [[BookmarksManager alloc] init];
return sBookmarksManager;
}
- (id)init
{
if ((self = [super init]))
{
[self registerNotificationListener];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString
{
[[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon:self
forURI:inURIString withUserData:requestor allowNetwork:NO];
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// callback for [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon]
- (void)imageLoadedNotification:(NSNotification*)notification
{
//NSLog(@"BookmarksManager imageLoadedNotification");
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
id requestor = [userInfo objectForKey:SiteIconLoadUserDataKey]; // requestor is a BookmarkItem
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
if (iconImage && [requestor isMemberOfClass:[BookmarkItem class]])
{
[requestor setSiteIcon:iconImage];
BookmarksService::BookmarkChanged([requestor contentNode], FALSE);
}
}
}
@end

Просмотреть файл

@ -78,6 +78,7 @@ class nsIDOMNode;
@class BookmarksDataSource;
@class CHHistoryDataSource;
@class CHExtendedTabView;
@class CHPageProxyIcon;
@interface BrowserWindowController : NSWindowController<CHFind>
{
@ -93,6 +94,7 @@ class nsIDOMNode;
IBOutlet NSWindow* mLocationSheetWindow;
IBOutlet NSTextField* mLocationSheetURLField;
IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock
IBOutlet CHPageProxyIcon* mProxyIcon;
IBOutlet id mSidebarBrowserView; // currently unused
IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource;
@ -162,6 +164,7 @@ class nsIDOMNode;
- (void)loadURL:(NSString*)aURLSpec referrer:(NSString*)aReferrer activate:(BOOL)activate;
- (void)updateLocationFields:(NSString *)locationString;
- (void)updateSiteIcons:(NSImage *)siteIconImage;
- (void)updateToolbarItems;
- (void)focusURLBar;

Просмотреть файл

@ -46,6 +46,7 @@
#import "CHHistoryDataSource.h"
#import "CHExtendedTabView.h"
#import "CHUserDefaults.h"
#import "CHPageProxyIcon.h"
#include "nsIWebNavigation.h"
#include "nsIDOMElement.h"
@ -947,6 +948,13 @@ static NSArray* sToolbarDefaults = nil;
// [[self window] display];
}
- (void)updateSiteIcons:(NSImage *)siteIconImage
{
if (siteIconImage == nil)
siteIconImage = [NSImage imageNamed:@"globe_ico"];
[mProxyIcon setImage:siteIconImage];
}
-(void)newTab:(BOOL)allowHomepage
{
CHIconTabViewItem* newTab = [[[CHIconTabViewItem alloc] initWithIdentifier: nil] autorelease];

Просмотреть файл

@ -25,15 +25,20 @@
#import <Appkit/Appkit.h>
class nsIDOMElement;
class BookmarksService;
@class BookmarkItem;
@interface CHBookmarksButton : NSButton {
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BOOL mIsFolder;
@interface CHBookmarksButton : NSButton
{
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BookmarksService* mBookmarksService;
BOOL mIsFolder;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService;
-(void)setElement: (nsIDOMElement*)aElt;
-(nsIDOMElement*)element;

Просмотреть файл

@ -39,9 +39,9 @@
@implementation CHBookmarksButton
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mElement = nsnull;
[self setBezelStyle: NSRegularSquareBezelStyle];
[self setButtonType: NSMomentaryChangeButton];
[self setBordered: NO];
@ -52,6 +52,15 @@
return self;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService
{
if ( (self = [self initWithFrame:frame]) ) {
mBookmarksService = bookmarksService;
[self setElement:element];
}
return self;
}
-(IBAction)openBookmark:(id)aSender
{
// See if we're a group.
@ -203,22 +212,24 @@
nsAutoString tag;
mElement->GetLocalName(tag);
NSImage* bookmarkImage = mBookmarksService->CreateIconForBookmark(aElt);
nsAutoString group;
mElement->GetAttribute(NS_LITERAL_STRING("group"), group);
if (!group.IsEmpty()) {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"groupbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
}
else if (tag.Equals(NS_LITERAL_STRING("folder"))) {
[self setImage: [NSImage imageNamed: @"folder"]];
[self setImage: bookmarkImage];
mIsFolder = YES;
}
else {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"smallbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
nsAutoString href;

Просмотреть файл

@ -28,12 +28,13 @@ class nsIDOMElement;
class BookmarksService;
class CHBookmarksButton;
@interface CHBookmarksToolbar : NSView {
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
@interface CHBookmarksToolbar : NSView
{
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
CHBookmarksButton* mDragInsertionButton;
int mDragInsertionPosition;
BOOL mIsShowing;
int mDragInsertionPosition;
BOOL mIsShowing;
}
-(void)initializeToolbar;

Просмотреть файл

@ -31,9 +31,14 @@
#include "nsIDOMElement.h"
#include "nsIContent.h"
@interface CHBookmarksToolbar(Private)
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element;
@end
@implementation CHBookmarksToolbar
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mBookmarks = nsnull;
mButtons = [[NSMutableArray alloc] init];
@ -95,8 +100,7 @@
while (child) {
nsCOMPtr<nsIDOMElement> childElt(do_QueryInterface(child));
if (childElt) {
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: childElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:childElt];
[self addSubview: button];
[mButtons addObject: button];
}
@ -111,8 +115,7 @@
-(void)addButton: (nsIDOMElement*)aElt atIndex: (int)aIndex
{
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: aElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:aElt];
[self addSubview: button];
[mButtons insertObject: button atIndex: aIndex];
if ([self isShown])
@ -453,4 +456,9 @@
}
}
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element
{
return [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17) element:element bookmarksService:mBookmarks] autorelease];
}
@end

Просмотреть файл

@ -51,6 +51,9 @@
NSTabViewItem* mTab;
NSWindow* mWindow;
NSImage* mSiteIconImage; // current proxy icon image, which may be a site icon (favicon).
NSString* mSiteIconURI; // uri from which we loaded the site icon
// the secure state of this browser. We need to hold it so that we can set
// the global lock icon whenever we become the primary. Value is one of
// security enums in nsIWebProgressListener.
@ -60,9 +63,9 @@
NSString* mTitle;
CHBrowserView* mBrowserView;
NSString* defaultStatus;
NSString* loadingStatus;
ToolTip* toolTip;
NSString* mDefaultStatusString;
NSString* mLoadingStatusString;
ToolTip* mToolTip;
BOOL mIsPrimary;
BOOL mIsBusy;

Просмотреть файл

@ -37,9 +37,12 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserWrapper.h"
#import "BrowserWindowController.h"
#import "BookmarksService.h"
#import "SiteIconProvider.h"
#import "CHIconTabViewItem.h"
#import "ToolTip.h"
#include "nsCOMPtr.h"
@ -64,8 +67,18 @@
static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
const NSString* kOfflineNotificationName = @"offlineModeChanged";
@interface CHBrowserWrapper(Private)
-(void) setPendingActive:(BOOL)active;
- (void)setPendingActive:(BOOL)active;
- (void)registerNotificationListener;
- (void)setSiteIconImage:(NSImage*)inSiteIcon;
- (void)setSiteIconURI:(NSString*)inSiteIconURI;
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI;
@end
@implementation CHBrowserWrapper
@ -85,10 +98,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
#endif
[[NSNotificationCenter defaultCenter] removeObserver: self];
[defaultStatus release];
[loadingStatus release];
[toolTip release];
[mSiteIconImage release];
[mSiteIconURI release];
[mDefaultStatusString release];
[mLoadingStatusString release];
[mToolTip release];
[super dealloc];
}
@ -105,7 +120,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
progress = nil;
progressSuper = nil;
mIsPrimary = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kOfflineNotificationName object:nil];
[mBrowserView setActive: NO];
}
@ -133,7 +148,13 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mIsBusy = NO;
mListenersAttached = NO;
mSecureState = nsIWebProgressListener::STATE_IS_INSECURE;
toolTip = [[ToolTip alloc] init];
mToolTip = [[ToolTip alloc] init];
//[self setSiteIconImage:[NSImage imageNamed:@"globe_ico"]];
//[self setSiteIconURI: [NSString string]];
[self registerNotificationListener];
}
return self;
}
@ -155,9 +176,9 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (!mIsBusy)
[progress removeFromSuperview];
defaultStatus = NULL;
loadingStatus = DOCUMENT_DONE_STRING;
[status setStringValue:loadingStatus];
mDefaultStatusString = NULL;
mLoadingStatusString = DOCUMENT_DONE_STRING;
[status setStringValue:mLoadingStatusString];
mIsPrimary = YES;
@ -181,11 +202,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (mWindowController) // Only register if we're the content area.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(offlineModeChanged:)
name:@"offlineModeChanged"
name:kOfflineNotificationName
object:nil];
// Update the URL bar.
[mWindowController updateLocationFields:[self getCurrentURLSpec]];
[mWindowController updateSiteIcons:mSiteIconImage];
if (mWindowController && !mListenersAttached) {
mListenersAttached = YES;
@ -209,7 +231,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
return [mBrowserView getCurrentURLSpec];
}
- (void)awakeFromNib
- (void)awakeFromNib
{
}
@ -239,17 +261,17 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLoadingStarted
{
if (defaultStatus) {
[defaultStatus release];
defaultStatus = NULL;
if (mDefaultStatusString) {
[mDefaultStatusString release];
mDefaultStatusString = NULL;
}
[progressSuper addSubview:progress];
[progress setIndeterminate:YES];
[progress startAnimation:self];
loadingStatus = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:loadingStatus];
mLoadingStatusString = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:mLoadingStatusString];
mIsBusy = YES;
[mTab setLabel: NSLocalizedString(@"TabLoading", @"")];
@ -271,12 +293,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[progress stopAnimation:self];
[progress removeFromSuperview];
loadingStatus = DOCUMENT_DONE_STRING;
if (defaultStatus) {
[status setStringValue:defaultStatus];
mLoadingStatusString = DOCUMENT_DONE_STRING;
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
mIsBusy = NO;
@ -316,8 +338,32 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLocationChange:(NSString*)urlSpec
{
BOOL useSiteIcons = [[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL];
BOOL siteIconLoadInitiated = NO;
SiteIconProvider* faviconProvider = [SiteIconProvider sharedFavoriteIconProvider];
NSString* faviconURI = [SiteIconProvider faviconLocationStringFromURI:urlSpec];
if (useSiteIcons && [faviconURI length] > 0)
{
// if the favicon uri has changed, fire off favicon load. When it completes, our
// imageLoadedNotification selector gets called.
if (![faviconURI isEqualToString:mSiteIconURI])
siteIconLoadInitiated = [faviconProvider loadFavoriteIcon:self forURI:urlSpec withUserData:nil allowNetwork:YES];
}
else
{
if ([urlSpec isEqualToString:@"about:blank"])
faviconURI = urlSpec;
else
faviconURI = @"";
}
if (!siteIconLoadInitiated)
[self updateSiteIconImage:nil withURI:faviconURI];
if (mIsPrimary)
[mWindowController updateLocationFields:urlSpec];
[mWindowController updateLocationFields:urlSpec];
}
- (void)onStatusChange:(NSString*)aStatusString
@ -342,20 +388,20 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)setStatus:(NSString *)statusString ofType:(NSStatusType)type
{
if (type == NSStatusTypeScriptDefault) {
if (defaultStatus) {
[defaultStatus release];
if (mDefaultStatusString) {
[mDefaultStatusString release];
}
defaultStatus = statusString;
if (defaultStatus) {
[defaultStatus retain];
mDefaultStatusString = statusString;
if (mDefaultStatusString) {
[mDefaultStatusString retain];
}
}
else if (!statusString) {
if (defaultStatus) {
[status setStringValue:defaultStatus];
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
}
else {
@ -418,12 +464,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onShowTooltip:(NSPoint)where withText:(NSString*)text
{
NSPoint point = [[self window] convertBaseToScreen:[self convertPoint: where toView:nil]];
[toolTip showToolTipAtPoint: point withString: text];
[mToolTip showToolTipAtPoint: point withString: text];
}
- (void)onHideTooltip
{
[toolTip closeToolTip];
[mToolTip closeToolTip];
}
// Called when a context menu should be shown.
@ -547,4 +593,77 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mActivateOnLoad = active;
}
- (void)setSiteIconImage:(NSImage*)inSiteIcon
{
[mSiteIconImage autorelease];
mSiteIconImage = [inSiteIcon retain];
}
- (void)setSiteIconURI:(NSString*)inSiteIconURI
{
[mSiteIconURI autorelease];
mSiteIconURI = [inSiteIconURI retain];
}
// A nil inSiteIcon image indicates that we should use the default icon
// If inSiteIconURI is "about:blank", we don't show any icon
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI
{
BOOL resetTabIcon = NO;
if (![mSiteIconURI isEqualToString:inSiteIconURI])
{
if (!inSiteIcon)
{
if (![inSiteIconURI isEqualToString:@"about:blank"])
inSiteIcon = [NSImage imageNamed:@"globe_ico"];
}
[self setSiteIconImage: inSiteIcon];
[self setSiteIconURI: inSiteIconURI];
// update the proxy icon
if (mIsPrimary)
[mWindowController updateSiteIcons:mSiteIconImage];
resetTabIcon = YES;
}
// update the tab icon
if ([mTab isMemberOfClass:[CHIconTabViewItem class]])
{
CHIconTabViewItem* tabItem = (CHIconTabViewItem*)mTab;
if (resetTabIcon || ![tabItem tabIcon])
[tabItem setTabIcon:mSiteIconImage];
}
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// called when [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon] completes
- (void)imageLoadedNotification:(NSNotification*)notification
{
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
NSString* siteIconURI = [userInfo objectForKey:SiteIconLoadURIKey];
// NSLog(@"CHBrowserWrapper imageLoadedNotification got image %@ and uri %@", iconImage, proxyImageURI);
if (iconImage == nil)
siteIconURI = @""; // go back to default image
[self updateSiteIconImage:iconImage withURI:siteIconURI];
}
}
@end

Просмотреть файл

@ -40,7 +40,8 @@
#import <Cocoa/Cocoa.h>
@interface CHIconTabViewItem : NSTabViewItem {
@interface CHIconTabViewItem : NSTabViewItem
{
NSImage *mTabIcon;
NSDictionary* mLabelAttributes;
}

Просмотреть файл

@ -39,8 +39,9 @@
*
* ***** END LICENSE BLOCK ***** */
#import "CHIconTabViewItem.h"
#import "NSString+Utils.h"
#import "CHIconTabViewItem.h"
//
// NSParagraphStyle has a line break mode which will automatically
@ -91,7 +92,7 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
[labelParagraphStyle setLineBreakMode:NSLineBreakByTruncatingMiddle];
#endif
[labelParagraphStyle setAlignment:NSCenterTextAlignment];
[labelParagraphStyle setAlignment:NSNaturalTextAlignment];
NSFont *labelFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
mLabelAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
@ -139,9 +140,9 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
if ([self tabIcon]) {
NSPoint drawPoint = NSMakePoint( (tabRect.origin.x), (tabRect.origin.y + 15.0) );
[[self tabIcon] compositeToPoint:drawPoint operation:NSCompositeSourceOver];
tabRect = NSMakeRect(NSMinX(tabRect)+15.0,
tabRect = NSMakeRect(NSMinX(tabRect) + 18.0,
NSMinY(tabRect),
NSWidth(tabRect)-15.0,
NSWidth(tabRect) - 18.0,
NSHeight(tabRect));
}

Просмотреть файл

@ -25,7 +25,7 @@
@interface CHPageProxyIcon : NSImageView
{
}
@end

Просмотреть файл

@ -24,13 +24,25 @@
#import "NSString+Utils.h"
#import "CHPageProxyIcon.h"
#import "BookmarksService.h"
#import "MainController.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
#include "nsString.h"
@implementation CHPageProxyIcon
- (void)awakeFromNib
{
}
- (void)dealloc
{
[super dealloc];
}
- (void) resetCursorRects
{
NSCursor* cursor;
@ -77,4 +89,5 @@
event: event pasteboard: pboard source: self slideBack: YES];
}
@end

Просмотреть файл

@ -35,12 +35,16 @@
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <Carbon/Carbon.h>
@interface CHPreferenceManager : NSObject {
class nsIPref;
@interface CHPreferenceManager : NSObject
{
NSUserDefaults* mDefaults;
ICInstance mInternetConfig;
nsIPref* mPrefs;
}
+ (CHPreferenceManager *)sharedInstance;
@ -54,4 +58,9 @@
- (NSString *) getICStringPref:(ConstStr255Param) prefKey;
- (NSString *) homePage:(BOOL) checkStartupPagePref;
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
@end

Просмотреть файл

@ -86,8 +86,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (void) dealloc
{
::ICStop(mInternetConfig);
NS_IF_RELEASE(mPrefs);
nsresult rv;
ICStop (mInternetConfig);
nsCOMPtr<nsIPrefService> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
//NSLog(@"Saving prefs file");
@ -100,7 +102,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (BOOL) initInternetConfig
{
OSStatus error;
error = ICStart (&mInternetConfig, 'CHIM');
error = ::ICStart(&mInternetConfig, 'CHIM');
if (error != noErr) {
// XXX throw here?
NSLog(@"Error initializing IC");
@ -178,6 +180,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
return NO;
}
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
mPrefs = prefs;
NS_IF_ADDREF(mPrefs);
[self syncMozillaPrefs];
return YES;
}
@ -191,9 +197,8 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
char strbuf[1024];
int numbuf;
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs) {
// XXXw. throw?
if (!mPrefs) {
NSLog(@"Mozilla prefs not set up successfully");
return;
}
@ -201,42 +206,42 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// something that chimera can deal with.
PRInt32 acceptCookies = 0;
static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior";
prefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
mPrefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
if ( acceptCookies == 1 ) { // accept foreign cookies, assume off
acceptCookies = 2;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
else if ( acceptCookies == 3 ) { // p3p, assume all cookies on
acceptCookies = 0;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
// get proxies from SystemConfiguration
prefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
prefs->ClearUserPref("network.proxy.http");
prefs->ClearUserPref("network.proxy.http_port");
prefs->ClearUserPref("network.proxy.ssl");
prefs->ClearUserPref("network.proxy.ssl_port");
prefs->ClearUserPref("network.proxy.ftp");
prefs->ClearUserPref("network.proxy.ftp_port");
prefs->ClearUserPref("network.proxy.gopher");
prefs->ClearUserPref("network.proxy.gopher_port");
prefs->ClearUserPref("network.proxy.socks");
prefs->ClearUserPref("network.proxy.socks_port");
prefs->ClearUserPref("network.proxy.no_proxies_on");
mPrefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
mPrefs->ClearUserPref("network.proxy.http");
mPrefs->ClearUserPref("network.proxy.http_port");
mPrefs->ClearUserPref("network.proxy.ssl");
mPrefs->ClearUserPref("network.proxy.ssl_port");
mPrefs->ClearUserPref("network.proxy.ftp");
mPrefs->ClearUserPref("network.proxy.ftp_port");
mPrefs->ClearUserPref("network.proxy.gopher");
mPrefs->ClearUserPref("network.proxy.gopher_port");
mPrefs->ClearUserPref("network.proxy.socks");
mPrefs->ClearUserPref("network.proxy.socks_port");
mPrefs->ClearUserPref("network.proxy.no_proxies_on");
if ((cfDictionary = SCDynamicStoreCopyProxies (NULL)) != NULL) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPEnable, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.http", strbuf);
mPrefs->SetCharPref("network.proxy.http", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.http_port", numbuf);
mPrefs->SetIntPref("network.proxy.http_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -245,13 +250,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ssl", strbuf);
mPrefs->SetCharPref("network.proxy.ssl", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ssl_port", numbuf);
mPrefs->SetIntPref("network.proxy.ssl_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -260,13 +265,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ftp", strbuf);
mPrefs->SetCharPref("network.proxy.ftp", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ftp_port", numbuf);
mPrefs->SetIntPref("network.proxy.ftp_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -275,13 +280,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.gopher", strbuf);
mPrefs->SetCharPref("network.proxy.gopher", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.gopher_port", numbuf);
mPrefs->SetIntPref("network.proxy.gopher_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -290,13 +295,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.socks", strbuf);
mPrefs->SetCharPref("network.proxy.socks", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.socks_port", numbuf);
mPrefs->SetIntPref("network.proxy.socks_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -305,7 +310,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
cfString = CFStringCreateByCombiningStrings (NULL, cfArray, CFSTR(", "));
if (CFStringGetLength (cfString) > 0) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
mPrefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
}
}
}
@ -313,24 +318,73 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
}
}
// convenience routines for mozilla prefs
- (NSString*)getMozillaPrefString: (const char*)prefName
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
NSMutableString *prefValue = [[[NSMutableString alloc] init] autorelease];
NSString *prefValue = @"";
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs) {
char *buf = nsnull;
nsresult rv = prefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
[prefValue setString:[NSString stringWithCString:buf]];
free(buf);
}
char *buf = nsnull;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
// prefs are UTF-8
prefValue = [NSString stringWithUTF8String:buf];
free(buf);
if (outSuccess) *outSuccess = YES;
} else {
if (outSuccess) *outSuccess = NO;
}
return prefValue;
}
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
// colors are stored in HTML-like #FFFFFF strings
NSString* colorString = [self getStringPref:prefName withSuccess:outSuccess];
NSColor* returnColor = [NSColor blackColor];
if ([colorString hasPrefix:@"#"] && [colorString length] == 7)
{
unsigned int redInt, greenInt, blueInt;
sscanf([colorString cString], "#%02x%02x%02x", &redInt, &greenInt, &blueInt);
float redFloat = ((float)redInt / 255.0);
float greenFloat = ((float)greenInt / 255.0);
float blueFloat = ((float)blueInt / 255.0);
returnColor = [NSColor colorWithCalibratedRed:redFloat green:greenFloat blue:blueFloat alpha:1.0f];
}
return returnColor;
}
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRBool boolPref = PR_FALSE;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
rv = mPrefs->GetBoolPref(prefName, &boolPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return boolPref ? YES : NO;
}
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRInt32 intPref = 0;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetIntPref(prefName, &intPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return intPref;
}
//- (BOOL) getICBoolPref:(ConstStr255Param) prefKey;
//{
@ -381,8 +435,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (NSString *) homePage:(BOOL)checkStartupPagePref
{
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs)
if (!mPrefs)
return @"about:blank";
PRInt32 mode = 1;
@ -394,14 +447,14 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// is true.
nsresult rv = NS_OK;
if ( checkStartupPagePref )
rv = prefs->GetIntPref("browser.startup.page", &mode);
rv = mPrefs->GetIntPref("browser.startup.page", &mode);
if (NS_FAILED(rv) || mode == 1) {
// see which home page to use
PRBool boolPref;
if (NS_SUCCEEDED(prefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
if (NS_SUCCEEDED(mPrefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
return [self getICStringPref:kICWWWHomePage];
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefs);
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(mPrefs);
if (!prefBranch) return @"about:blank";
NSString* homepagePref = nil;
@ -411,10 +464,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
homepagePref = NSLocalizedStringFromTable( @"HomePageDefault", @"WebsiteDefaults", nil);
// and let's copy this into the homepage pref if it's not bad
if (![homepagePref isEqualToString:@"HomePageDefault"])
prefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
mPrefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
}
else {
homepagePref = [self getMozillaPrefString:"browser.startup.homepage"];
homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL];
}
if (homepagePref && [homepagePref length] > 0 && ![homepagePref isEqualToString:@"HomePageDefault"])

Просмотреть файл

@ -75,7 +75,7 @@ class BookmarksService;
FindDlgController* mFindDialog;
MVPreferencesController* preferencesController;
MVPreferencesController* mPreferencesController;
NSString* mStartURL;
}

Просмотреть файл

@ -132,7 +132,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[mBookmarksMenu setAutoenablesItems: NO];
mMenuBookmarks = new BookmarksService((BookmarksDataSource*)nil);
mMenuBookmarks->AddObserver();
mMenuBookmarks->ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::gMainController = self;
// Initialize offline mode.
@ -152,6 +152,29 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
*/
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferencesController release];
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
-(IBAction)newWindow:(id)aSender
{
// If we have a key window, have it autosave its dimensions before
@ -455,29 +478,6 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[[[controller getBrowserWrapper] getBrowserView] setActive: YES];
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
// Bookmarks menu actions.
-(IBAction) importBookmarks:(id)aSender
{
@ -558,10 +558,10 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (MVPreferencesController *)preferencesController
{
if (!preferencesController) {
preferencesController = [[MVPreferencesController sharedInstance] retain];
if (!mPreferencesController) {
mPreferencesController = [[MVPreferencesController sharedInstance] retain];
}
return preferencesController;
return mPreferencesController;
}
- (void)displayPreferencesWindow:sender

Просмотреть файл

@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
extern NSString* RemoteDataLoadRequestNotificationName;
extern NSString* RemoteDataLoadRequestURIKey;
extern NSString* RemoteDataLoadRequestDataKey;
extern NSString* RemoteDataLoadRequestUserDataKey;
extern NSString* RemoteDataLoadRequestResultKey;
// RemoteDataProvider is a class that can be used to do asynchronous loads
// from URIs using necko, and passing back the result of the load to a
// callback in NSData.
//
// Clients can either implement the RemoteLoadListener protocol and call
// loadURI directly, or they can register with the [NSNotification defaultCenter]
// for 'RemoteDataLoadRequestNotificationName' notifications, and catch all loads
// that happen that way.
@protocol RemoteLoadListener
// called when the load completes, or fails. If the status code is a failure code,
// data may be nil.
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status;
@end
class RemoteURILoadManager;
@interface RemoteDataProvider : NSObject<RemoteLoadListener>
{
RemoteURILoadManager* mLoadManager;
}
+ (RemoteDataProvider*)sharedRemoteDataProvider;
// generic method. You can load any URI asynchronously with this selector,
// and the listener will get the contents of the URI in an NSData.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
// specific request to load a remote file. The sender (or any other object), if
// registered with the notification center, will receive a notification when
// the load completes. The 'target' becomes the 'object' of the notification.
// The notification name is given by NSString* RemoteDataLoadRequestNotificationName above.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
@end

Просмотреть файл

@ -0,0 +1,298 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "RemoteDataProvider.h"
#include "nsISupports.h"
#include "nsHashtable.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* RemoteDataLoadRequestNotificationName = @"remoteload_notification_name";
NSString* RemoteDataLoadRequestURIKey = @"remoteload_uri_key";
NSString* RemoteDataLoadRequestDataKey = @"remoteload_data_key";
NSString* RemoteDataLoadRequestUserDataKey = @"remoteload_user_data_key";
NSString* RemoteDataLoadRequestResultKey = @"remoteload_result_key";
// this has to retain the load listener, to ensure that the listener lives long
// enough to receive notifications. We have to be careful to avoid ref cycles.
class StreamLoaderContext : public nsISupports
{
public:
StreamLoaderContext(id<RemoteLoadListener> inLoadListener, id inUserData, id inTarget, const nsAString& inURI)
: mLoadListener(inLoadListener)
, mTarget(inTarget)
, mUserData(inUserData)
, mURI(inURI)
{
NS_INIT_ISUPPORTS();
[mLoadListener retain];
}
virtual ~StreamLoaderContext()
{
[mLoadListener release];
}
NS_DECL_ISUPPORTS
void LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength);
const nsAString& GetURI() { return mURI; }
protected:
id<RemoteLoadListener> mLoadListener; // retained
id mTarget; // not retained
id mUserData; // not retained
nsString mURI;
};
NS_IMPL_ISUPPORTS1(StreamLoaderContext, nsISupports)
void StreamLoaderContext::LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength)
{
if (mLoadListener)
{
NSData* loadData = nil;
if (NS_SUCCEEDED(inLoadStatus))
loadData = [NSData dataWithBytes:inData length:inDataLength];
[mLoadListener doneRemoteLoad:[NSString stringWith_nsAString:mURI] forTarget:mTarget withUserData:mUserData data:loadData status:inLoadStatus];
}
}
class RemoteURILoadManager : public nsIStreamLoaderObserver
{
public:
RemoteURILoadManager();
virtual ~RemoteURILoadManager();
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
nsresult Init();
nsresult RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener, id userData, id target, PRBool allowNetworking);
protected:
nsSupportsHashtable mStreamLoaderHash; // hash of active stream loads, keyed on URI
nsCOMPtr<nsICacheSession> mCacheSession;
};
RemoteURILoadManager::RemoteURILoadManager()
{
NS_INIT_ISUPPORTS();
}
RemoteURILoadManager::~RemoteURILoadManager()
{
}
NS_IMPL_ISUPPORTS1(RemoteURILoadManager, nsIStreamLoaderObserver)
NS_IMETHODIMP RemoteURILoadManager::OnStreamComplete(nsIStreamLoader *loader, nsISupports *ctxt, nsresult status, PRUint32 resultLength, const char *result)
{
StreamLoaderContext* loaderContext = NS_STATIC_CAST(StreamLoaderContext*, ctxt);
if (loaderContext)
{
loaderContext->LoadComplete(status, (const void*)result, resultLength);
// remove the stream loader from the hash table
nsStringKey uriKey(loaderContext->GetURI());
PRBool removed = mStreamLoaderHash.Remove(&uriKey);
}
return NS_OK;
}
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
nsresult RemoteURILoadManager::Init()
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession("HTTP", nsICache::STORE_ANYWHERE,
nsICache::STREAM_BASED, getter_AddRefs(mCacheSession));
return rv;
}
nsresult RemoteURILoadManager::RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener,
id userData, id target, PRBool allowNetworking)
{
nsresult rv;
#if 0
// if no networking is allowed, make sure it's in the cache
if (!allowNetworking)
{
if (!mCacheSession)
return NS_ERROR_FAILURE;
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
rv = mCacheSession->OpenCacheEntry(NS_ConvertUCS2toUTF8(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc)
return NS_ERROR_FAILURE;
}
#endif
nsStringKey uriKey(inURI);
// first make sure that there isn't another entry in the hash for this
nsCOMPtr<nsISupports> foundStreamSupports = mStreamLoaderHash.Get(&uriKey);
if (foundStreamSupports)
return NS_OK;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), inURI);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsISupports> loaderContext = new StreamLoaderContext(loadListener, userData, target, inURI);
nsLoadFlags loadFlags = (allowNetworking) ? nsIRequest::LOAD_NORMAL : nsIRequest::LOAD_FROM_CACHE;
nsCOMPtr<nsIStreamLoader> streamLoader;
rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), uri, this, loaderContext, nsnull, nsnull, loadFlags);
if (NS_FAILED(rv))
{
NSLog(@"NS_NewStreamLoader for favicon failed");
return rv;
}
#ifdef DEBUG_smfr
NSLog(@"RequestURILoad called for %@", [NSString stringWith_nsAString: inURI]);
#endif
// put the stream loader into the hash table
nsCOMPtr<nsISupports> streamLoaderAsSupports = do_QueryInterface(streamLoader);
mStreamLoaderHash.Put(&uriKey, streamLoaderAsSupports);
return NS_OK;
}
#pragma mark -
@implementation RemoteDataProvider
+ (RemoteDataProvider*)sharedRemoteDataProvider
{
static RemoteDataProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[RemoteDataProvider alloc] init];
// we probably need to register for NSApplicationWillTerminateNotification notifications
// and delete this then.
}
return sIconProvider;
}
- (id)init
{
if ((self = [super init]))
{
mLoadManager = new RemoteURILoadManager;
NS_ADDREF(mLoadManager);
}
return self;
}
- (void)dealloc
{
NS_IF_RELEASE(mLoadManager);
[super dealloc];
}
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
//NSLog(@"loadURI called with %@", inURI);
if (mLoadManager && [inURI length] > 0)
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsresult rv = mLoadManager->RequestURILoad(uriString, inListener, userData, target, (PRBool)inNetworkOK);
if (NS_FAILED(rv))
{
NSLog(@"RequestURILoad failed for @%", inURI);
return NO;
}
}
return YES;
}
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
return [self loadURI:inURI forTarget:target withListener:self withUserData:userData allowNetworking:inNetworkOK];
}
// our own load listener callback
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, RemoteDataLoadRequestURIKey,
data, RemoteDataLoadRequestDataKey,
userData, RemoteDataLoadRequestUserDataKey,
[NSNumber numberWithInt:status], RemoteDataLoadRequestResultKey,
nil];
NSLog(@"remoteLoadDone with status %d and length %d", status, [data length]);
[[NSNotificationCenter defaultCenter] postNotificationName: RemoteDataLoadRequestNotificationName
object:target userInfo:notificationData];
}
@end

69
camino/SiteIconProvider.h Normal file
Просмотреть файл

@ -0,0 +1,69 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Cocoa/Cocoa.h>
#import "RemoteDataProvider.h"
extern NSString* SiteIconLoadNotificationName;
extern NSString* SiteIconLoadImageKey;
extern NSString* SiteIconLoadURIKey;
extern NSString* SiteIconLoadUserDataKey;
class NeckoCacheHelper;
@interface SiteIconProvider : NSObject<RemoteLoadListener>
{
NeckoCacheHelper* mMissedIconsCacheHelper;
}
+ (SiteIconProvider*)sharedFavoriteIconProvider;
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI;
// Start a favicon.ico load for the given URI, which can be any URI.
// The caller will get a 'SiteIconLoadNotificationName' notification
// when the load is done, with the image at the 'SiteIconLoadImageKey' key
// in the notifcation userInfo. The caller will have had to register with the
// NSNotifcationCenter in order to receive this notifcation. The notification
// is dispatched with 'sender' as the object.
// This method returns YES if the uri request was dispatched (i.e. if we know
// that we've looked for, and failed to find, this icon before). If it returns
// YES, then the 'SiteIconLoadNotificationName' notification will be sent out.
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork;
@end

330
camino/SiteIconProvider.mm Normal file
Просмотреть файл

@ -0,0 +1,330 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "SiteIconProvider.h"
#include "prtime.h"
#include "nsString.h"
#include "nsISupports.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* SiteIconLoadNotificationName = @"siteicon_load_notification";
NSString* SiteIconLoadImageKey = @"siteicon_load_image";
NSString* SiteIconLoadURIKey = @"siteicon_load_uri";
NSString* SiteIconLoadUserDataKey = @"siteicon_load_user_data";
static inline PRUint32 PRTimeToSeconds(PRTime t_usec)
{
PRTime usec_per_sec;
PRUint32 t_sec;
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
LL_DIV(t_usec, t_usec, usec_per_sec);
LL_L2I(t_sec, t_usec);
return t_sec;
}
class NeckoCacheHelper
{
public:
NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue);
~NeckoCacheHelper() {}
nsresult Init(const char* inCacheSessionName);
nsresult ExistsInCache(const nsACString& inURI, PRBool* outExists);
nsresult PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds);
nsresult ClearCache();
protected:
const char* mMetaElement;
const char* mMetaValue;
nsCOMPtr<nsICacheSession> mCacheSession;
};
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
NeckoCacheHelper::NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue)
: mMetaElement(inMetaElement)
, mMetaValue(inMetaValue)
{
}
nsresult NeckoCacheHelper::Init(const char* inCacheSessionName)
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession(inCacheSessionName,
nsICache::STORE_ANYWHERE, nsICache::STREAM_BASED,
getter_AddRefs(mCacheSession));
if (NS_FAILED(rv))
return rv;
return NS_OK;
}
nsresult NeckoCacheHelper::ExistsInCache(const nsACString& inURI, PRBool* outExists)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
*outExists = NS_SUCCEEDED(rv) && (entryDesc != NULL);
return NS_OK;
}
nsresult NeckoCacheHelper::PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_WRITE, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc) return rv;
nsCacheAccessMode accessMode;
rv = entryDesc->GetAccessGranted(&accessMode);
if (NS_FAILED(rv))
return rv;
if (accessMode != nsICache::ACCESS_WRITE)
return NS_ERROR_FAILURE;
entryDesc->SetMetaDataElement(mMetaElement, mMetaValue); // just set a bit of meta data.
entryDesc->SetExpirationTime(PRTimeToSeconds(PR_Now()) + inExpirationTimeSeconds);
entryDesc->MarkValid();
entryDesc->Close();
return NS_OK;
}
nsresult NeckoCacheHelper::ClearCache()
{
NS_ASSERTION(mCacheSession, "No cache session");
return mCacheSession->EvictEntries();
}
#pragma mark -
static nsresult MakeFaviconURIFromURI(const nsAString& inURIString, nsAString& outFaviconURI)
{
outFaviconURI.Truncate(0);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), inURIString);
if (NS_FAILED(rv))
return rv;
// check for http/https
PRBool isHTTP = PR_FALSE, isHTTPS = PR_FALSE;
uri->SchemeIs("http", &isHTTP);
uri->SchemeIs("https", &isHTTPS);
if (!isHTTP && !isHTTPS)
return NS_OK;
PRInt32 port;
uri->GetPort(&port);
nsXPIDLCString scheme;
uri->GetScheme(scheme);
nsXPIDLCString host;
uri->GetHost(host);
nsCAutoString faviconURI = scheme;
faviconURI.Append("://");
faviconURI.Append(host);
if (port != -1) {
faviconURI.Append(':');
faviconURI.AppendInt(port);
}
faviconURI.Append("/favicon.ico");
outFaviconURI.Assign(NS_ConvertUTF8toUCS2(faviconURI));
return NS_OK;
}
@interface SiteIconProvider(Private)
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds;
- (BOOL)inMissedIconsCache:(const nsAString&)inURI;
@end
@implementation SiteIconProvider
- (id)init
{
if ((self = [super init]))
{
mMissedIconsCacheHelper = new NeckoCacheHelper("Favicon", "Missed");
nsresult rv = mMissedIconsCacheHelper->Init("MissedIconsCache");
if (NS_FAILED(rv)) {
delete mMissedIconsCacheHelper;
mMissedIconsCacheHelper = NULL;
}
}
return self;
}
- (void)dealloc
{
delete mMissedIconsCacheHelper;
[super dealloc];
}
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds
{
if (mMissedIconsCacheHelper)
{
nsresult rv = mMissedIconsCacheHelper->PutInCache(NS_ConvertUCS2toUTF8(inURI), inExpSeconds);
//NSLog(@"Putting %@ in missed icon cache", [NSString stringWith_nsAString:inURI]);
}
}
- (BOOL)inMissedIconsCache:(const nsAString&)inURI
{
PRBool inCache = PR_FALSE;
if (mMissedIconsCacheHelper)
mMissedIconsCacheHelper->ExistsInCache(NS_ConvertUCS2toUTF8(inURI), &inCache);
//NSLog(@"%@ in missed icon cache: %d", [NSString stringWith_nsAString:inURI], inCache);
return inCache;
}
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork
{
// look for a favicon
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
if (faviconURIString.Length() == 0)
return NO;
NSString* faviconString = [NSString stringWith_nsAString:faviconURIString];
// is this uri already in the missing icons cache?
if ([self inMissedIconsCache:faviconURIString])
return NO;
RemoteDataProvider* dataProvider = [RemoteDataProvider sharedRemoteDataProvider];
return [dataProvider loadURI:faviconString forTarget:sender withListener:self withUserData:userData allowNetworking:inAllowNetwork];
}
#define SITE_ICON_EXPIRATION_SECONDS (60 * 60 * 24 * 7) // 1 week
// this is called on the main thread
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
BOOL loadOK = NS_SUCCEEDED(status) && (data != nil);
// it's hard to tell if the favicon load succeeded or not. Even if the file
// does not exist, servers will send back a 404 page with a 0 status.
// So we just go ahead and try to make the image; it will return nil on
// failure.
NSImage* faviconImage = [[NSImage alloc] initWithData:data];
BOOL gotImageData = loadOK && (faviconImage != nil);
if (!gotImageData)
[self addToMissedIconsCache:uriString withExpirationSeconds:SITE_ICON_EXPIRATION_SECONDS];
[faviconImage setScalesWhenResized:YES];
[faviconImage setSize:NSMakeSize(16, 16)];
// we always send out the notification, so that clients know
// about failed requests
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, SiteIconLoadURIKey,
faviconImage, SiteIconLoadImageKey, // may be nil
userData, SiteIconLoadUserDataKey,
nil];
[[NSNotificationCenter defaultCenter] postNotificationName: SiteIconLoadNotificationName
object:target userInfo:notificationData];
}
#pragma mark -
+ (SiteIconProvider*)sharedFavoriteIconProvider
{
static SiteIconProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[SiteIconProvider alloc] init];
}
return sIconProvider;
}
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
return [NSString stringWith_nsAString:faviconURIString];
}
@end

Просмотреть файл

@ -75,7 +75,7 @@ class BookmarksService;
FindDlgController* mFindDialog;
MVPreferencesController* preferencesController;
MVPreferencesController* mPreferencesController;
NSString* mStartURL;
}

Просмотреть файл

@ -132,7 +132,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[mBookmarksMenu setAutoenablesItems: NO];
mMenuBookmarks = new BookmarksService((BookmarksDataSource*)nil);
mMenuBookmarks->AddObserver();
mMenuBookmarks->ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::gMainController = self;
// Initialize offline mode.
@ -152,6 +152,29 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
*/
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferencesController release];
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
-(IBAction)newWindow:(id)aSender
{
// If we have a key window, have it autosave its dimensions before
@ -455,29 +478,6 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[[[controller getBrowserWrapper] getBrowserView] setActive: YES];
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
// Bookmarks menu actions.
-(IBAction) importBookmarks:(id)aSender
{
@ -558,10 +558,10 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (MVPreferencesController *)preferencesController
{
if (!preferencesController) {
preferencesController = [[MVPreferencesController sharedInstance] retain];
if (!mPreferencesController) {
mPreferencesController = [[MVPreferencesController sharedInstance] retain];
}
return preferencesController;
return mPreferencesController;
}
- (void)displayPreferencesWindow:sender

Просмотреть файл

@ -25,15 +25,20 @@
#import <Appkit/Appkit.h>
class nsIDOMElement;
class BookmarksService;
@class BookmarkItem;
@interface CHBookmarksButton : NSButton {
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BOOL mIsFolder;
@interface CHBookmarksButton : NSButton
{
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BookmarksService* mBookmarksService;
BOOL mIsFolder;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService;
-(void)setElement: (nsIDOMElement*)aElt;
-(nsIDOMElement*)element;

Просмотреть файл

@ -39,9 +39,9 @@
@implementation CHBookmarksButton
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mElement = nsnull;
[self setBezelStyle: NSRegularSquareBezelStyle];
[self setButtonType: NSMomentaryChangeButton];
[self setBordered: NO];
@ -52,6 +52,15 @@
return self;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService
{
if ( (self = [self initWithFrame:frame]) ) {
mBookmarksService = bookmarksService;
[self setElement:element];
}
return self;
}
-(IBAction)openBookmark:(id)aSender
{
// See if we're a group.
@ -203,22 +212,24 @@
nsAutoString tag;
mElement->GetLocalName(tag);
NSImage* bookmarkImage = mBookmarksService->CreateIconForBookmark(aElt);
nsAutoString group;
mElement->GetAttribute(NS_LITERAL_STRING("group"), group);
if (!group.IsEmpty()) {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"groupbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
}
else if (tag.Equals(NS_LITERAL_STRING("folder"))) {
[self setImage: [NSImage imageNamed: @"folder"]];
[self setImage: bookmarkImage];
mIsFolder = YES;
}
else {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"smallbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
nsAutoString href;

Просмотреть файл

@ -49,6 +49,7 @@ class BookmarksService;
@class BookmarkInfoController;
// data source for the bookmarks sidebar. We make one per browser window.
@interface BookmarksDataSource : NSObject
{
BookmarksService* mBookmarks;
@ -106,14 +107,16 @@ class BookmarksService;
@interface BookmarkItem : NSObject
{
nsIContent* mContentNode;
NSImage* mSiteIcon;
}
- (nsIContent*)contentNode;
- (void)setContentNode: (nsIContent*)aContentNode;
- (void)setSiteIcon:(NSImage*)image;
- (NSString*)url;
- (NSImage*)siteIcon;
- (NSNumber*)contentID;
- (id)copyWithZone:(NSZone *)aZone;
- (BOOL)isFolder;
@end

Просмотреть файл

@ -41,6 +41,7 @@
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "SiteIconProvider.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
@ -55,17 +56,16 @@
#include "nsVoidArray.h"
#import "BookmarksService.h"
#import "StringUtils.h"
@implementation BookmarksDataSource
-(id) init
{
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
}
-(void) awakeFromNib
@ -86,16 +86,16 @@
-(void) ensureBookmarks
{
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
}
-(IBAction)addBookmark:(id)aSender
@ -530,20 +530,10 @@
//Get the cell of the text attachment.
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
//Figure out which image to add, and set the cell's image.
// Use the bookmark groups image for groups.
if ([self outlineView:outlineView isItemExpandable:item]) {
nsIContent* content = [item contentNode];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, BookmarksService::gGroupAtom, group);
if (!group.IsEmpty())
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"groupbookmark"]];
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]];
}
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
NSImage* bookmarkImage = mBookmarks->CreateIconForBookmark(elt);
[attachmentAttrStringCell setImage:bookmarkImage];
//Insert the image
[cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString];
@ -855,7 +845,16 @@
@end
#pragma mark -
@implementation BookmarkItem
-(void)dealloc
{
[mSiteIcon release];
[super dealloc];
}
-(nsIContent*)contentNode
{
return mContentNode;
@ -887,6 +886,18 @@
return [NSString stringWith_nsAString: href];
}
- (void)setSiteIcon:(NSImage*)image
{
//NSLog(@"Setting site icon for %@", [self url]);
[mSiteIcon autorelease];
mSiteIcon = [image retain];
}
- (NSImage*)siteIcon
{
return mSiteIcon;
}
-(void)setContentNode: (nsIContent*)aContentNode
{
mContentNode = aContentNode;
@ -896,6 +907,7 @@
{
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
[copy setContentNode: mContentNode];
[copy setSiteIcon: mSiteIcon];
return copy;
}

Просмотреть файл

@ -53,6 +53,9 @@ class nsIDOMHTMLDocument;
@class BookmarksDataSource;
@class BookmarkItem;
// despite appearances, BookmarksService is not a singleton. We make one for the bookmarks menu,
// one each per BookmarksDataSource, and one per bookmarks toolbar. It relies on a bunch of global
// variables, which is evil.
class BookmarksService
{
public:
@ -63,6 +66,7 @@ public:
void AddObserver();
void RemoveObserver();
public:
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
@ -71,7 +75,6 @@ public:
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
static void DeleteBookmark(nsIDOMElement* aBookmark);
public:
static void GetRootContent(nsIContent** aResult);
static BookmarkItem* GetRootItem();
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
@ -87,6 +90,8 @@ public:
static void ConstructAddBookmarkFolderList(NSPopUpButton* aPopup, BookmarkItem* aItem);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static void EnsureToolbarRoot();
static void ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc);
@ -96,8 +101,6 @@ public:
static NSString* ResolveKeyword(NSString* aKeyword);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
@ -139,3 +142,23 @@ private:
CHBookmarksToolbar* mToolbar;
BookmarksDataSource* mDataSource;
};
// singleton bookmarks manager object
@interface BookmarksManager : NSObject
{
}
+ (BookmarksManager*)sharedBookmarksManager;
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString;
@end

Просмотреть файл

@ -37,12 +37,13 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserView.h"
#import "BookmarksService.h"
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "CHIconTabViewItem.h"
#import "StringUtils.h"
#import "SiteIconProvider.h"
#include "nsCRT.h"
#include "nsString.h"
@ -106,6 +107,7 @@ NSMutableDictionary* BookmarksService::gDictionary = nil;
MainController* BookmarksService::gMainController = nil;
NSMenu* BookmarksService::gBookmarksMenu = nil;
nsIDOMElement* BookmarksService::gToolbarRoot = nsnull;
nsIAtom* BookmarksService::gBookmarkAtom = nsnull;
nsIAtom* BookmarksService::gDescriptionAtom = nsnull;
nsIAtom* BookmarksService::gFolderAtom = nsnull;
@ -114,8 +116,11 @@ nsIAtom* BookmarksService::gHrefAtom = nsnull;
nsIAtom* BookmarksService::gKeywordAtom = nsnull;
nsIAtom* BookmarksService::gNameAtom = nsnull;
nsIAtom* BookmarksService::gOpenAtom = nsnull;
nsVoidArray* BookmarksService::gInstances = nsnull;
BOOL BookmarksService::gBookmarksFileReadOK = NO;
int BookmarksService::CHInsertNone = 0;
int BookmarksService::CHInsertInto = 1;
int BookmarksService::CHInsertBefore = 2;
@ -137,6 +142,54 @@ BookmarksService::~BookmarksService()
{
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
#pragma mark -
void
BookmarksService::GetRootContent(nsIContent** aResult)
{
@ -211,7 +264,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
}
void
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -258,7 +311,7 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool
}
void
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -289,6 +342,10 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
aItem->GetAttr(kNameSpaceID_None, gNameAtom, name);
NSString* bookmarkTitle = [[NSString stringWith_nsAString: name] stringByTruncatingTo:80 at:kTruncateAtMiddle];
[childItem setTitle: bookmarkTitle];
// and reset the image
BookmarkItem* item = GetWrapperFor(aItem);
[childItem setImage: [item siteIcon]];
}
}
@ -298,7 +355,7 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
}
void
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances)
return;
@ -343,51 +400,6 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bo
FlushBookmarks();
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
void
BookmarksService::AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt)
@ -601,6 +613,40 @@ BookmarksService::FlushBookmarks()
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"groupbookmark"];
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
// fire off a proxy icon load
if ([[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL])
{
nsAutoString href;
content->GetAttr(kNameSpaceID_None, gHrefAtom, href);
if (href.Length() > 0)
{
BookmarkItem* contentItem = BookmarksService::GetWrapperFor(content);
if ([contentItem siteIcon])
return [contentItem siteIcon];
if (contentItem && ![contentItem siteIcon])
[[BookmarksManager sharedBookmarksManager] loadProxyImageFor:contentItem withURI:[NSString stringWith_nsAString:href]];
}
}
return [NSImage imageNamed:@"smallbookmark"];
}
void BookmarksService::EnsureToolbarRoot()
{
if (gToolbarRoot)
@ -763,18 +809,21 @@ BookmarksService::AddMenuBookmark(NSMenu* aMenu, nsIContent* aParent, nsIContent
nsAutoString group;
aChild->GetAttr(kNameSpaceID_None, gGroupAtom, group);
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aChild));
NSImage* menuItemImage = BookmarksService::CreateIconForBookmark(elt);
if (group.IsEmpty() && tagName == gFolderAtom) {
NSMenu* menu = [[[NSMenu alloc] initWithTitle: title] autorelease];
[aMenu setSubmenu: menu forItem: menuItem];
[menu setAutoenablesItems: NO];
[menuItem setImage: [NSImage imageNamed:@"folder"]];
[menuItem setImage: menuItemImage];
ConstructBookmarksMenu(menu, aChild);
}
else {
if (group.IsEmpty())
[menuItem setImage: [NSImage imageNamed:@"smallbookmark"]];
[menuItem setImage: menuItemImage];
else
[menuItem setImage: [NSImage imageNamed:@"groupbookmark"]];
[menuItem setImage: menuItemImage];
[menuItem setTarget: gMainController];
[menuItem setAction: @selector(openMenuBookmark:)];
@ -997,10 +1046,12 @@ BookmarksService::ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc)
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(bookmarksRoot));
nsCOMPtr<nsIContent> childContent(do_QueryInterface(importedRootElement));
#if 0
// XXX testing
if (gDictionary)
[gDictionary removeAllObjects];
#endif
// this will save the file
BookmarkAdded(parentContent, childContent, true /* flush */);
}
@ -1072,24 +1123,7 @@ BookmarksService::ResolveKeyword(NSString* aKeyword)
content->GetAttr(kNameSpaceID_None, gHrefAtom, url);
return [NSString stringWith_nsAString: url];
}
return [NSString stringWithCString:""];
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"smallgroup"];
return [NSImage imageNamed:@"groupbookmark"];
return [NSString string];
}
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
@ -1292,3 +1326,78 @@ BookmarksService::PerformURLDrop(BookmarkItem* parentItem, BookmarkItem* beforeI
return YES;
}
#pragma mark -
@interface BookmarksManager(Private)
- (void)registerNotificationListener;
- (void)imageLoadedNotification:(NSNotification*)notification;
@end
@implementation BookmarksManager
+ (BookmarksManager*)sharedBookmarksManager;
{
static BookmarksManager* sBookmarksManager = nil;
if (!sBookmarksManager)
sBookmarksManager = [[BookmarksManager alloc] init];
return sBookmarksManager;
}
- (id)init
{
if ((self = [super init]))
{
[self registerNotificationListener];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString
{
[[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon:self
forURI:inURIString withUserData:requestor allowNetwork:NO];
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// callback for [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon]
- (void)imageLoadedNotification:(NSNotification*)notification
{
//NSLog(@"BookmarksManager imageLoadedNotification");
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
id requestor = [userInfo objectForKey:SiteIconLoadUserDataKey]; // requestor is a BookmarkItem
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
if (iconImage && [requestor isMemberOfClass:[BookmarkItem class]])
{
[requestor setSiteIcon:iconImage];
BookmarksService::BookmarkChanged([requestor contentNode], FALSE);
}
}
}
@end

Просмотреть файл

@ -28,12 +28,13 @@ class nsIDOMElement;
class BookmarksService;
class CHBookmarksButton;
@interface CHBookmarksToolbar : NSView {
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
@interface CHBookmarksToolbar : NSView
{
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
CHBookmarksButton* mDragInsertionButton;
int mDragInsertionPosition;
BOOL mIsShowing;
int mDragInsertionPosition;
BOOL mIsShowing;
}
-(void)initializeToolbar;

Просмотреть файл

@ -31,9 +31,14 @@
#include "nsIDOMElement.h"
#include "nsIContent.h"
@interface CHBookmarksToolbar(Private)
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element;
@end
@implementation CHBookmarksToolbar
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mBookmarks = nsnull;
mButtons = [[NSMutableArray alloc] init];
@ -95,8 +100,7 @@
while (child) {
nsCOMPtr<nsIDOMElement> childElt(do_QueryInterface(child));
if (childElt) {
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: childElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:childElt];
[self addSubview: button];
[mButtons addObject: button];
}
@ -111,8 +115,7 @@
-(void)addButton: (nsIDOMElement*)aElt atIndex: (int)aIndex
{
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: aElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:aElt];
[self addSubview: button];
[mButtons insertObject: button atIndex: aIndex];
if ([self isShown])
@ -453,4 +456,9 @@
}
}
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element
{
return [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17) element:element bookmarksService:mBookmarks] autorelease];
}
@end

Просмотреть файл

@ -78,6 +78,7 @@ class nsIDOMNode;
@class BookmarksDataSource;
@class CHHistoryDataSource;
@class CHExtendedTabView;
@class CHPageProxyIcon;
@interface BrowserWindowController : NSWindowController<CHFind>
{
@ -93,6 +94,7 @@ class nsIDOMNode;
IBOutlet NSWindow* mLocationSheetWindow;
IBOutlet NSTextField* mLocationSheetURLField;
IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock
IBOutlet CHPageProxyIcon* mProxyIcon;
IBOutlet id mSidebarBrowserView; // currently unused
IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource;
@ -162,6 +164,7 @@ class nsIDOMNode;
- (void)loadURL:(NSString*)aURLSpec referrer:(NSString*)aReferrer activate:(BOOL)activate;
- (void)updateLocationFields:(NSString *)locationString;
- (void)updateSiteIcons:(NSImage *)siteIconImage;
- (void)updateToolbarItems;
- (void)focusURLBar;

Просмотреть файл

@ -46,6 +46,7 @@
#import "CHHistoryDataSource.h"
#import "CHExtendedTabView.h"
#import "CHUserDefaults.h"
#import "CHPageProxyIcon.h"
#include "nsIWebNavigation.h"
#include "nsIDOMElement.h"
@ -947,6 +948,13 @@ static NSArray* sToolbarDefaults = nil;
// [[self window] display];
}
- (void)updateSiteIcons:(NSImage *)siteIconImage
{
if (siteIconImage == nil)
siteIconImage = [NSImage imageNamed:@"globe_ico"];
[mProxyIcon setImage:siteIconImage];
}
-(void)newTab:(BOOL)allowHomepage
{
CHIconTabViewItem* newTab = [[[CHIconTabViewItem alloc] initWithIdentifier: nil] autorelease];

Просмотреть файл

@ -51,6 +51,9 @@
NSTabViewItem* mTab;
NSWindow* mWindow;
NSImage* mSiteIconImage; // current proxy icon image, which may be a site icon (favicon).
NSString* mSiteIconURI; // uri from which we loaded the site icon
// the secure state of this browser. We need to hold it so that we can set
// the global lock icon whenever we become the primary. Value is one of
// security enums in nsIWebProgressListener.
@ -60,9 +63,9 @@
NSString* mTitle;
CHBrowserView* mBrowserView;
NSString* defaultStatus;
NSString* loadingStatus;
ToolTip* toolTip;
NSString* mDefaultStatusString;
NSString* mLoadingStatusString;
ToolTip* mToolTip;
BOOL mIsPrimary;
BOOL mIsBusy;

Просмотреть файл

@ -37,9 +37,12 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserWrapper.h"
#import "BrowserWindowController.h"
#import "BookmarksService.h"
#import "SiteIconProvider.h"
#import "CHIconTabViewItem.h"
#import "ToolTip.h"
#include "nsCOMPtr.h"
@ -64,8 +67,18 @@
static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
const NSString* kOfflineNotificationName = @"offlineModeChanged";
@interface CHBrowserWrapper(Private)
-(void) setPendingActive:(BOOL)active;
- (void)setPendingActive:(BOOL)active;
- (void)registerNotificationListener;
- (void)setSiteIconImage:(NSImage*)inSiteIcon;
- (void)setSiteIconURI:(NSString*)inSiteIconURI;
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI;
@end
@implementation CHBrowserWrapper
@ -85,10 +98,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
#endif
[[NSNotificationCenter defaultCenter] removeObserver: self];
[defaultStatus release];
[loadingStatus release];
[toolTip release];
[mSiteIconImage release];
[mSiteIconURI release];
[mDefaultStatusString release];
[mLoadingStatusString release];
[mToolTip release];
[super dealloc];
}
@ -105,7 +120,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
progress = nil;
progressSuper = nil;
mIsPrimary = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kOfflineNotificationName object:nil];
[mBrowserView setActive: NO];
}
@ -133,7 +148,13 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mIsBusy = NO;
mListenersAttached = NO;
mSecureState = nsIWebProgressListener::STATE_IS_INSECURE;
toolTip = [[ToolTip alloc] init];
mToolTip = [[ToolTip alloc] init];
//[self setSiteIconImage:[NSImage imageNamed:@"globe_ico"]];
//[self setSiteIconURI: [NSString string]];
[self registerNotificationListener];
}
return self;
}
@ -155,9 +176,9 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (!mIsBusy)
[progress removeFromSuperview];
defaultStatus = NULL;
loadingStatus = DOCUMENT_DONE_STRING;
[status setStringValue:loadingStatus];
mDefaultStatusString = NULL;
mLoadingStatusString = DOCUMENT_DONE_STRING;
[status setStringValue:mLoadingStatusString];
mIsPrimary = YES;
@ -181,11 +202,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (mWindowController) // Only register if we're the content area.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(offlineModeChanged:)
name:@"offlineModeChanged"
name:kOfflineNotificationName
object:nil];
// Update the URL bar.
[mWindowController updateLocationFields:[self getCurrentURLSpec]];
[mWindowController updateSiteIcons:mSiteIconImage];
if (mWindowController && !mListenersAttached) {
mListenersAttached = YES;
@ -209,7 +231,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
return [mBrowserView getCurrentURLSpec];
}
- (void)awakeFromNib
- (void)awakeFromNib
{
}
@ -239,17 +261,17 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLoadingStarted
{
if (defaultStatus) {
[defaultStatus release];
defaultStatus = NULL;
if (mDefaultStatusString) {
[mDefaultStatusString release];
mDefaultStatusString = NULL;
}
[progressSuper addSubview:progress];
[progress setIndeterminate:YES];
[progress startAnimation:self];
loadingStatus = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:loadingStatus];
mLoadingStatusString = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:mLoadingStatusString];
mIsBusy = YES;
[mTab setLabel: NSLocalizedString(@"TabLoading", @"")];
@ -271,12 +293,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[progress stopAnimation:self];
[progress removeFromSuperview];
loadingStatus = DOCUMENT_DONE_STRING;
if (defaultStatus) {
[status setStringValue:defaultStatus];
mLoadingStatusString = DOCUMENT_DONE_STRING;
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
mIsBusy = NO;
@ -316,8 +338,32 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLocationChange:(NSString*)urlSpec
{
BOOL useSiteIcons = [[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL];
BOOL siteIconLoadInitiated = NO;
SiteIconProvider* faviconProvider = [SiteIconProvider sharedFavoriteIconProvider];
NSString* faviconURI = [SiteIconProvider faviconLocationStringFromURI:urlSpec];
if (useSiteIcons && [faviconURI length] > 0)
{
// if the favicon uri has changed, fire off favicon load. When it completes, our
// imageLoadedNotification selector gets called.
if (![faviconURI isEqualToString:mSiteIconURI])
siteIconLoadInitiated = [faviconProvider loadFavoriteIcon:self forURI:urlSpec withUserData:nil allowNetwork:YES];
}
else
{
if ([urlSpec isEqualToString:@"about:blank"])
faviconURI = urlSpec;
else
faviconURI = @"";
}
if (!siteIconLoadInitiated)
[self updateSiteIconImage:nil withURI:faviconURI];
if (mIsPrimary)
[mWindowController updateLocationFields:urlSpec];
[mWindowController updateLocationFields:urlSpec];
}
- (void)onStatusChange:(NSString*)aStatusString
@ -342,20 +388,20 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)setStatus:(NSString *)statusString ofType:(NSStatusType)type
{
if (type == NSStatusTypeScriptDefault) {
if (defaultStatus) {
[defaultStatus release];
if (mDefaultStatusString) {
[mDefaultStatusString release];
}
defaultStatus = statusString;
if (defaultStatus) {
[defaultStatus retain];
mDefaultStatusString = statusString;
if (mDefaultStatusString) {
[mDefaultStatusString retain];
}
}
else if (!statusString) {
if (defaultStatus) {
[status setStringValue:defaultStatus];
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
}
else {
@ -418,12 +464,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onShowTooltip:(NSPoint)where withText:(NSString*)text
{
NSPoint point = [[self window] convertBaseToScreen:[self convertPoint: where toView:nil]];
[toolTip showToolTipAtPoint: point withString: text];
[mToolTip showToolTipAtPoint: point withString: text];
}
- (void)onHideTooltip
{
[toolTip closeToolTip];
[mToolTip closeToolTip];
}
// Called when a context menu should be shown.
@ -547,4 +593,77 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mActivateOnLoad = active;
}
- (void)setSiteIconImage:(NSImage*)inSiteIcon
{
[mSiteIconImage autorelease];
mSiteIconImage = [inSiteIcon retain];
}
- (void)setSiteIconURI:(NSString*)inSiteIconURI
{
[mSiteIconURI autorelease];
mSiteIconURI = [inSiteIconURI retain];
}
// A nil inSiteIcon image indicates that we should use the default icon
// If inSiteIconURI is "about:blank", we don't show any icon
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI
{
BOOL resetTabIcon = NO;
if (![mSiteIconURI isEqualToString:inSiteIconURI])
{
if (!inSiteIcon)
{
if (![inSiteIconURI isEqualToString:@"about:blank"])
inSiteIcon = [NSImage imageNamed:@"globe_ico"];
}
[self setSiteIconImage: inSiteIcon];
[self setSiteIconURI: inSiteIconURI];
// update the proxy icon
if (mIsPrimary)
[mWindowController updateSiteIcons:mSiteIconImage];
resetTabIcon = YES;
}
// update the tab icon
if ([mTab isMemberOfClass:[CHIconTabViewItem class]])
{
CHIconTabViewItem* tabItem = (CHIconTabViewItem*)mTab;
if (resetTabIcon || ![tabItem tabIcon])
[tabItem setTabIcon:mSiteIconImage];
}
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// called when [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon] completes
- (void)imageLoadedNotification:(NSNotification*)notification
{
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
NSString* siteIconURI = [userInfo objectForKey:SiteIconLoadURIKey];
// NSLog(@"CHBrowserWrapper imageLoadedNotification got image %@ and uri %@", iconImage, proxyImageURI);
if (iconImage == nil)
siteIconURI = @""; // go back to default image
[self updateSiteIconImage:iconImage withURI:siteIconURI];
}
}
@end

Просмотреть файл

@ -25,7 +25,7 @@
@interface CHPageProxyIcon : NSImageView
{
}
@end

Просмотреть файл

@ -24,13 +24,25 @@
#import "NSString+Utils.h"
#import "CHPageProxyIcon.h"
#import "BookmarksService.h"
#import "MainController.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
#include "nsString.h"
@implementation CHPageProxyIcon
- (void)awakeFromNib
{
}
- (void)dealloc
{
[super dealloc];
}
- (void) resetCursorRects
{
NSCursor* cursor;
@ -77,4 +89,5 @@
event: event pasteboard: pboard source: self slideBack: YES];
}
@end

Просмотреть файл

@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
extern NSString* RemoteDataLoadRequestNotificationName;
extern NSString* RemoteDataLoadRequestURIKey;
extern NSString* RemoteDataLoadRequestDataKey;
extern NSString* RemoteDataLoadRequestUserDataKey;
extern NSString* RemoteDataLoadRequestResultKey;
// RemoteDataProvider is a class that can be used to do asynchronous loads
// from URIs using necko, and passing back the result of the load to a
// callback in NSData.
//
// Clients can either implement the RemoteLoadListener protocol and call
// loadURI directly, or they can register with the [NSNotification defaultCenter]
// for 'RemoteDataLoadRequestNotificationName' notifications, and catch all loads
// that happen that way.
@protocol RemoteLoadListener
// called when the load completes, or fails. If the status code is a failure code,
// data may be nil.
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status;
@end
class RemoteURILoadManager;
@interface RemoteDataProvider : NSObject<RemoteLoadListener>
{
RemoteURILoadManager* mLoadManager;
}
+ (RemoteDataProvider*)sharedRemoteDataProvider;
// generic method. You can load any URI asynchronously with this selector,
// and the listener will get the contents of the URI in an NSData.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
// specific request to load a remote file. The sender (or any other object), if
// registered with the notification center, will receive a notification when
// the load completes. The 'target' becomes the 'object' of the notification.
// The notification name is given by NSString* RemoteDataLoadRequestNotificationName above.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
@end

Просмотреть файл

@ -0,0 +1,298 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "RemoteDataProvider.h"
#include "nsISupports.h"
#include "nsHashtable.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* RemoteDataLoadRequestNotificationName = @"remoteload_notification_name";
NSString* RemoteDataLoadRequestURIKey = @"remoteload_uri_key";
NSString* RemoteDataLoadRequestDataKey = @"remoteload_data_key";
NSString* RemoteDataLoadRequestUserDataKey = @"remoteload_user_data_key";
NSString* RemoteDataLoadRequestResultKey = @"remoteload_result_key";
// this has to retain the load listener, to ensure that the listener lives long
// enough to receive notifications. We have to be careful to avoid ref cycles.
class StreamLoaderContext : public nsISupports
{
public:
StreamLoaderContext(id<RemoteLoadListener> inLoadListener, id inUserData, id inTarget, const nsAString& inURI)
: mLoadListener(inLoadListener)
, mTarget(inTarget)
, mUserData(inUserData)
, mURI(inURI)
{
NS_INIT_ISUPPORTS();
[mLoadListener retain];
}
virtual ~StreamLoaderContext()
{
[mLoadListener release];
}
NS_DECL_ISUPPORTS
void LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength);
const nsAString& GetURI() { return mURI; }
protected:
id<RemoteLoadListener> mLoadListener; // retained
id mTarget; // not retained
id mUserData; // not retained
nsString mURI;
};
NS_IMPL_ISUPPORTS1(StreamLoaderContext, nsISupports)
void StreamLoaderContext::LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength)
{
if (mLoadListener)
{
NSData* loadData = nil;
if (NS_SUCCEEDED(inLoadStatus))
loadData = [NSData dataWithBytes:inData length:inDataLength];
[mLoadListener doneRemoteLoad:[NSString stringWith_nsAString:mURI] forTarget:mTarget withUserData:mUserData data:loadData status:inLoadStatus];
}
}
class RemoteURILoadManager : public nsIStreamLoaderObserver
{
public:
RemoteURILoadManager();
virtual ~RemoteURILoadManager();
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
nsresult Init();
nsresult RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener, id userData, id target, PRBool allowNetworking);
protected:
nsSupportsHashtable mStreamLoaderHash; // hash of active stream loads, keyed on URI
nsCOMPtr<nsICacheSession> mCacheSession;
};
RemoteURILoadManager::RemoteURILoadManager()
{
NS_INIT_ISUPPORTS();
}
RemoteURILoadManager::~RemoteURILoadManager()
{
}
NS_IMPL_ISUPPORTS1(RemoteURILoadManager, nsIStreamLoaderObserver)
NS_IMETHODIMP RemoteURILoadManager::OnStreamComplete(nsIStreamLoader *loader, nsISupports *ctxt, nsresult status, PRUint32 resultLength, const char *result)
{
StreamLoaderContext* loaderContext = NS_STATIC_CAST(StreamLoaderContext*, ctxt);
if (loaderContext)
{
loaderContext->LoadComplete(status, (const void*)result, resultLength);
// remove the stream loader from the hash table
nsStringKey uriKey(loaderContext->GetURI());
PRBool removed = mStreamLoaderHash.Remove(&uriKey);
}
return NS_OK;
}
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
nsresult RemoteURILoadManager::Init()
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession("HTTP", nsICache::STORE_ANYWHERE,
nsICache::STREAM_BASED, getter_AddRefs(mCacheSession));
return rv;
}
nsresult RemoteURILoadManager::RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener,
id userData, id target, PRBool allowNetworking)
{
nsresult rv;
#if 0
// if no networking is allowed, make sure it's in the cache
if (!allowNetworking)
{
if (!mCacheSession)
return NS_ERROR_FAILURE;
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
rv = mCacheSession->OpenCacheEntry(NS_ConvertUCS2toUTF8(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc)
return NS_ERROR_FAILURE;
}
#endif
nsStringKey uriKey(inURI);
// first make sure that there isn't another entry in the hash for this
nsCOMPtr<nsISupports> foundStreamSupports = mStreamLoaderHash.Get(&uriKey);
if (foundStreamSupports)
return NS_OK;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), inURI);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsISupports> loaderContext = new StreamLoaderContext(loadListener, userData, target, inURI);
nsLoadFlags loadFlags = (allowNetworking) ? nsIRequest::LOAD_NORMAL : nsIRequest::LOAD_FROM_CACHE;
nsCOMPtr<nsIStreamLoader> streamLoader;
rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), uri, this, loaderContext, nsnull, nsnull, loadFlags);
if (NS_FAILED(rv))
{
NSLog(@"NS_NewStreamLoader for favicon failed");
return rv;
}
#ifdef DEBUG_smfr
NSLog(@"RequestURILoad called for %@", [NSString stringWith_nsAString: inURI]);
#endif
// put the stream loader into the hash table
nsCOMPtr<nsISupports> streamLoaderAsSupports = do_QueryInterface(streamLoader);
mStreamLoaderHash.Put(&uriKey, streamLoaderAsSupports);
return NS_OK;
}
#pragma mark -
@implementation RemoteDataProvider
+ (RemoteDataProvider*)sharedRemoteDataProvider
{
static RemoteDataProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[RemoteDataProvider alloc] init];
// we probably need to register for NSApplicationWillTerminateNotification notifications
// and delete this then.
}
return sIconProvider;
}
- (id)init
{
if ((self = [super init]))
{
mLoadManager = new RemoteURILoadManager;
NS_ADDREF(mLoadManager);
}
return self;
}
- (void)dealloc
{
NS_IF_RELEASE(mLoadManager);
[super dealloc];
}
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
//NSLog(@"loadURI called with %@", inURI);
if (mLoadManager && [inURI length] > 0)
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsresult rv = mLoadManager->RequestURILoad(uriString, inListener, userData, target, (PRBool)inNetworkOK);
if (NS_FAILED(rv))
{
NSLog(@"RequestURILoad failed for @%", inURI);
return NO;
}
}
return YES;
}
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
return [self loadURI:inURI forTarget:target withListener:self withUserData:userData allowNetworking:inNetworkOK];
}
// our own load listener callback
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, RemoteDataLoadRequestURIKey,
data, RemoteDataLoadRequestDataKey,
userData, RemoteDataLoadRequestUserDataKey,
[NSNumber numberWithInt:status], RemoteDataLoadRequestResultKey,
nil];
NSLog(@"remoteLoadDone with status %d and length %d", status, [data length]);
[[NSNotificationCenter defaultCenter] postNotificationName: RemoteDataLoadRequestNotificationName
object:target userInfo:notificationData];
}
@end

Просмотреть файл

@ -0,0 +1,69 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Cocoa/Cocoa.h>
#import "RemoteDataProvider.h"
extern NSString* SiteIconLoadNotificationName;
extern NSString* SiteIconLoadImageKey;
extern NSString* SiteIconLoadURIKey;
extern NSString* SiteIconLoadUserDataKey;
class NeckoCacheHelper;
@interface SiteIconProvider : NSObject<RemoteLoadListener>
{
NeckoCacheHelper* mMissedIconsCacheHelper;
}
+ (SiteIconProvider*)sharedFavoriteIconProvider;
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI;
// Start a favicon.ico load for the given URI, which can be any URI.
// The caller will get a 'SiteIconLoadNotificationName' notification
// when the load is done, with the image at the 'SiteIconLoadImageKey' key
// in the notifcation userInfo. The caller will have had to register with the
// NSNotifcationCenter in order to receive this notifcation. The notification
// is dispatched with 'sender' as the object.
// This method returns YES if the uri request was dispatched (i.e. if we know
// that we've looked for, and failed to find, this icon before). If it returns
// YES, then the 'SiteIconLoadNotificationName' notification will be sent out.
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork;
@end

Просмотреть файл

@ -0,0 +1,330 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "SiteIconProvider.h"
#include "prtime.h"
#include "nsString.h"
#include "nsISupports.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* SiteIconLoadNotificationName = @"siteicon_load_notification";
NSString* SiteIconLoadImageKey = @"siteicon_load_image";
NSString* SiteIconLoadURIKey = @"siteicon_load_uri";
NSString* SiteIconLoadUserDataKey = @"siteicon_load_user_data";
static inline PRUint32 PRTimeToSeconds(PRTime t_usec)
{
PRTime usec_per_sec;
PRUint32 t_sec;
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
LL_DIV(t_usec, t_usec, usec_per_sec);
LL_L2I(t_sec, t_usec);
return t_sec;
}
class NeckoCacheHelper
{
public:
NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue);
~NeckoCacheHelper() {}
nsresult Init(const char* inCacheSessionName);
nsresult ExistsInCache(const nsACString& inURI, PRBool* outExists);
nsresult PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds);
nsresult ClearCache();
protected:
const char* mMetaElement;
const char* mMetaValue;
nsCOMPtr<nsICacheSession> mCacheSession;
};
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
NeckoCacheHelper::NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue)
: mMetaElement(inMetaElement)
, mMetaValue(inMetaValue)
{
}
nsresult NeckoCacheHelper::Init(const char* inCacheSessionName)
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession(inCacheSessionName,
nsICache::STORE_ANYWHERE, nsICache::STREAM_BASED,
getter_AddRefs(mCacheSession));
if (NS_FAILED(rv))
return rv;
return NS_OK;
}
nsresult NeckoCacheHelper::ExistsInCache(const nsACString& inURI, PRBool* outExists)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
*outExists = NS_SUCCEEDED(rv) && (entryDesc != NULL);
return NS_OK;
}
nsresult NeckoCacheHelper::PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_WRITE, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc) return rv;
nsCacheAccessMode accessMode;
rv = entryDesc->GetAccessGranted(&accessMode);
if (NS_FAILED(rv))
return rv;
if (accessMode != nsICache::ACCESS_WRITE)
return NS_ERROR_FAILURE;
entryDesc->SetMetaDataElement(mMetaElement, mMetaValue); // just set a bit of meta data.
entryDesc->SetExpirationTime(PRTimeToSeconds(PR_Now()) + inExpirationTimeSeconds);
entryDesc->MarkValid();
entryDesc->Close();
return NS_OK;
}
nsresult NeckoCacheHelper::ClearCache()
{
NS_ASSERTION(mCacheSession, "No cache session");
return mCacheSession->EvictEntries();
}
#pragma mark -
static nsresult MakeFaviconURIFromURI(const nsAString& inURIString, nsAString& outFaviconURI)
{
outFaviconURI.Truncate(0);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), inURIString);
if (NS_FAILED(rv))
return rv;
// check for http/https
PRBool isHTTP = PR_FALSE, isHTTPS = PR_FALSE;
uri->SchemeIs("http", &isHTTP);
uri->SchemeIs("https", &isHTTPS);
if (!isHTTP && !isHTTPS)
return NS_OK;
PRInt32 port;
uri->GetPort(&port);
nsXPIDLCString scheme;
uri->GetScheme(scheme);
nsXPIDLCString host;
uri->GetHost(host);
nsCAutoString faviconURI = scheme;
faviconURI.Append("://");
faviconURI.Append(host);
if (port != -1) {
faviconURI.Append(':');
faviconURI.AppendInt(port);
}
faviconURI.Append("/favicon.ico");
outFaviconURI.Assign(NS_ConvertUTF8toUCS2(faviconURI));
return NS_OK;
}
@interface SiteIconProvider(Private)
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds;
- (BOOL)inMissedIconsCache:(const nsAString&)inURI;
@end
@implementation SiteIconProvider
- (id)init
{
if ((self = [super init]))
{
mMissedIconsCacheHelper = new NeckoCacheHelper("Favicon", "Missed");
nsresult rv = mMissedIconsCacheHelper->Init("MissedIconsCache");
if (NS_FAILED(rv)) {
delete mMissedIconsCacheHelper;
mMissedIconsCacheHelper = NULL;
}
}
return self;
}
- (void)dealloc
{
delete mMissedIconsCacheHelper;
[super dealloc];
}
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds
{
if (mMissedIconsCacheHelper)
{
nsresult rv = mMissedIconsCacheHelper->PutInCache(NS_ConvertUCS2toUTF8(inURI), inExpSeconds);
//NSLog(@"Putting %@ in missed icon cache", [NSString stringWith_nsAString:inURI]);
}
}
- (BOOL)inMissedIconsCache:(const nsAString&)inURI
{
PRBool inCache = PR_FALSE;
if (mMissedIconsCacheHelper)
mMissedIconsCacheHelper->ExistsInCache(NS_ConvertUCS2toUTF8(inURI), &inCache);
//NSLog(@"%@ in missed icon cache: %d", [NSString stringWith_nsAString:inURI], inCache);
return inCache;
}
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork
{
// look for a favicon
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
if (faviconURIString.Length() == 0)
return NO;
NSString* faviconString = [NSString stringWith_nsAString:faviconURIString];
// is this uri already in the missing icons cache?
if ([self inMissedIconsCache:faviconURIString])
return NO;
RemoteDataProvider* dataProvider = [RemoteDataProvider sharedRemoteDataProvider];
return [dataProvider loadURI:faviconString forTarget:sender withListener:self withUserData:userData allowNetworking:inAllowNetwork];
}
#define SITE_ICON_EXPIRATION_SECONDS (60 * 60 * 24 * 7) // 1 week
// this is called on the main thread
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
BOOL loadOK = NS_SUCCEEDED(status) && (data != nil);
// it's hard to tell if the favicon load succeeded or not. Even if the file
// does not exist, servers will send back a 404 page with a 0 status.
// So we just go ahead and try to make the image; it will return nil on
// failure.
NSImage* faviconImage = [[NSImage alloc] initWithData:data];
BOOL gotImageData = loadOK && (faviconImage != nil);
if (!gotImageData)
[self addToMissedIconsCache:uriString withExpirationSeconds:SITE_ICON_EXPIRATION_SECONDS];
[faviconImage setScalesWhenResized:YES];
[faviconImage setSize:NSMakeSize(16, 16)];
// we always send out the notification, so that clients know
// about failed requests
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, SiteIconLoadURIKey,
faviconImage, SiteIconLoadImageKey, // may be nil
userData, SiteIconLoadUserDataKey,
nil];
[[NSNotificationCenter defaultCenter] postNotificationName: SiteIconLoadNotificationName
object:target userInfo:notificationData];
}
#pragma mark -
+ (SiteIconProvider*)sharedFavoriteIconProvider
{
static SiteIconProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[SiteIconProvider alloc] init];
}
return sIconProvider;
}
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
return [NSString stringWith_nsAString:faviconURIString];
}
@end

Просмотреть файл

@ -40,7 +40,8 @@
#import <Cocoa/Cocoa.h>
@interface CHIconTabViewItem : NSTabViewItem {
@interface CHIconTabViewItem : NSTabViewItem
{
NSImage *mTabIcon;
NSDictionary* mLabelAttributes;
}

Просмотреть файл

@ -39,8 +39,9 @@
*
* ***** END LICENSE BLOCK ***** */
#import "CHIconTabViewItem.h"
#import "NSString+Utils.h"
#import "CHIconTabViewItem.h"
//
// NSParagraphStyle has a line break mode which will automatically
@ -91,7 +92,7 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
[labelParagraphStyle setLineBreakMode:NSLineBreakByTruncatingMiddle];
#endif
[labelParagraphStyle setAlignment:NSCenterTextAlignment];
[labelParagraphStyle setAlignment:NSNaturalTextAlignment];
NSFont *labelFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
mLabelAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
@ -139,9 +140,9 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
if ([self tabIcon]) {
NSPoint drawPoint = NSMakePoint( (tabRect.origin.x), (tabRect.origin.y + 15.0) );
[[self tabIcon] compositeToPoint:drawPoint operation:NSCompositeSourceOver];
tabRect = NSMakeRect(NSMinX(tabRect)+15.0,
tabRect = NSMakeRect(NSMinX(tabRect) + 18.0,
NSMinY(tabRect),
NSWidth(tabRect)-15.0,
NSWidth(tabRect) - 18.0,
NSHeight(tabRect));
}

Просмотреть файл

@ -35,12 +35,16 @@
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <Carbon/Carbon.h>
@interface CHPreferenceManager : NSObject {
class nsIPref;
@interface CHPreferenceManager : NSObject
{
NSUserDefaults* mDefaults;
ICInstance mInternetConfig;
nsIPref* mPrefs;
}
+ (CHPreferenceManager *)sharedInstance;
@ -54,4 +58,9 @@
- (NSString *) getICStringPref:(ConstStr255Param) prefKey;
- (NSString *) homePage:(BOOL) checkStartupPagePref;
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
@end

Просмотреть файл

@ -86,8 +86,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (void) dealloc
{
::ICStop(mInternetConfig);
NS_IF_RELEASE(mPrefs);
nsresult rv;
ICStop (mInternetConfig);
nsCOMPtr<nsIPrefService> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
//NSLog(@"Saving prefs file");
@ -100,7 +102,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (BOOL) initInternetConfig
{
OSStatus error;
error = ICStart (&mInternetConfig, 'CHIM');
error = ::ICStart(&mInternetConfig, 'CHIM');
if (error != noErr) {
// XXX throw here?
NSLog(@"Error initializing IC");
@ -178,6 +180,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
return NO;
}
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
mPrefs = prefs;
NS_IF_ADDREF(mPrefs);
[self syncMozillaPrefs];
return YES;
}
@ -191,9 +197,8 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
char strbuf[1024];
int numbuf;
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs) {
// XXXw. throw?
if (!mPrefs) {
NSLog(@"Mozilla prefs not set up successfully");
return;
}
@ -201,42 +206,42 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// something that chimera can deal with.
PRInt32 acceptCookies = 0;
static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior";
prefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
mPrefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
if ( acceptCookies == 1 ) { // accept foreign cookies, assume off
acceptCookies = 2;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
else if ( acceptCookies == 3 ) { // p3p, assume all cookies on
acceptCookies = 0;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
// get proxies from SystemConfiguration
prefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
prefs->ClearUserPref("network.proxy.http");
prefs->ClearUserPref("network.proxy.http_port");
prefs->ClearUserPref("network.proxy.ssl");
prefs->ClearUserPref("network.proxy.ssl_port");
prefs->ClearUserPref("network.proxy.ftp");
prefs->ClearUserPref("network.proxy.ftp_port");
prefs->ClearUserPref("network.proxy.gopher");
prefs->ClearUserPref("network.proxy.gopher_port");
prefs->ClearUserPref("network.proxy.socks");
prefs->ClearUserPref("network.proxy.socks_port");
prefs->ClearUserPref("network.proxy.no_proxies_on");
mPrefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
mPrefs->ClearUserPref("network.proxy.http");
mPrefs->ClearUserPref("network.proxy.http_port");
mPrefs->ClearUserPref("network.proxy.ssl");
mPrefs->ClearUserPref("network.proxy.ssl_port");
mPrefs->ClearUserPref("network.proxy.ftp");
mPrefs->ClearUserPref("network.proxy.ftp_port");
mPrefs->ClearUserPref("network.proxy.gopher");
mPrefs->ClearUserPref("network.proxy.gopher_port");
mPrefs->ClearUserPref("network.proxy.socks");
mPrefs->ClearUserPref("network.proxy.socks_port");
mPrefs->ClearUserPref("network.proxy.no_proxies_on");
if ((cfDictionary = SCDynamicStoreCopyProxies (NULL)) != NULL) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPEnable, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.http", strbuf);
mPrefs->SetCharPref("network.proxy.http", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.http_port", numbuf);
mPrefs->SetIntPref("network.proxy.http_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -245,13 +250,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ssl", strbuf);
mPrefs->SetCharPref("network.proxy.ssl", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ssl_port", numbuf);
mPrefs->SetIntPref("network.proxy.ssl_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -260,13 +265,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ftp", strbuf);
mPrefs->SetCharPref("network.proxy.ftp", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ftp_port", numbuf);
mPrefs->SetIntPref("network.proxy.ftp_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -275,13 +280,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.gopher", strbuf);
mPrefs->SetCharPref("network.proxy.gopher", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.gopher_port", numbuf);
mPrefs->SetIntPref("network.proxy.gopher_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -290,13 +295,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.socks", strbuf);
mPrefs->SetCharPref("network.proxy.socks", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.socks_port", numbuf);
mPrefs->SetIntPref("network.proxy.socks_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -305,7 +310,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
cfString = CFStringCreateByCombiningStrings (NULL, cfArray, CFSTR(", "));
if (CFStringGetLength (cfString) > 0) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
mPrefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
}
}
}
@ -313,24 +318,73 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
}
}
// convenience routines for mozilla prefs
- (NSString*)getMozillaPrefString: (const char*)prefName
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
NSMutableString *prefValue = [[[NSMutableString alloc] init] autorelease];
NSString *prefValue = @"";
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs) {
char *buf = nsnull;
nsresult rv = prefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
[prefValue setString:[NSString stringWithCString:buf]];
free(buf);
}
char *buf = nsnull;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
// prefs are UTF-8
prefValue = [NSString stringWithUTF8String:buf];
free(buf);
if (outSuccess) *outSuccess = YES;
} else {
if (outSuccess) *outSuccess = NO;
}
return prefValue;
}
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
// colors are stored in HTML-like #FFFFFF strings
NSString* colorString = [self getStringPref:prefName withSuccess:outSuccess];
NSColor* returnColor = [NSColor blackColor];
if ([colorString hasPrefix:@"#"] && [colorString length] == 7)
{
unsigned int redInt, greenInt, blueInt;
sscanf([colorString cString], "#%02x%02x%02x", &redInt, &greenInt, &blueInt);
float redFloat = ((float)redInt / 255.0);
float greenFloat = ((float)greenInt / 255.0);
float blueFloat = ((float)blueInt / 255.0);
returnColor = [NSColor colorWithCalibratedRed:redFloat green:greenFloat blue:blueFloat alpha:1.0f];
}
return returnColor;
}
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRBool boolPref = PR_FALSE;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
rv = mPrefs->GetBoolPref(prefName, &boolPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return boolPref ? YES : NO;
}
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRInt32 intPref = 0;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetIntPref(prefName, &intPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return intPref;
}
//- (BOOL) getICBoolPref:(ConstStr255Param) prefKey;
//{
@ -381,8 +435,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (NSString *) homePage:(BOOL)checkStartupPagePref
{
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs)
if (!mPrefs)
return @"about:blank";
PRInt32 mode = 1;
@ -394,14 +447,14 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// is true.
nsresult rv = NS_OK;
if ( checkStartupPagePref )
rv = prefs->GetIntPref("browser.startup.page", &mode);
rv = mPrefs->GetIntPref("browser.startup.page", &mode);
if (NS_FAILED(rv) || mode == 1) {
// see which home page to use
PRBool boolPref;
if (NS_SUCCEEDED(prefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
if (NS_SUCCEEDED(mPrefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
return [self getICStringPref:kICWWWHomePage];
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefs);
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(mPrefs);
if (!prefBranch) return @"about:blank";
NSString* homepagePref = nil;
@ -411,10 +464,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
homepagePref = NSLocalizedStringFromTable( @"HomePageDefault", @"WebsiteDefaults", nil);
// and let's copy this into the homepage pref if it's not bad
if (![homepagePref isEqualToString:@"HomePageDefault"])
prefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
mPrefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
}
else {
homepagePref = [self getMozillaPrefString:"browser.startup.homepage"];
homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL];
}
if (homepagePref && [homepagePref length] > 0 && ![homepagePref isEqualToString:@"HomePageDefault"])

Просмотреть файл

@ -49,6 +49,7 @@ class BookmarksService;
@class BookmarkInfoController;
// data source for the bookmarks sidebar. We make one per browser window.
@interface BookmarksDataSource : NSObject
{
BookmarksService* mBookmarks;
@ -106,14 +107,16 @@ class BookmarksService;
@interface BookmarkItem : NSObject
{
nsIContent* mContentNode;
NSImage* mSiteIcon;
}
- (nsIContent*)contentNode;
- (void)setContentNode: (nsIContent*)aContentNode;
- (void)setSiteIcon:(NSImage*)image;
- (NSString*)url;
- (NSImage*)siteIcon;
- (NSNumber*)contentID;
- (id)copyWithZone:(NSZone *)aZone;
- (BOOL)isFolder;
@end

Просмотреть файл

@ -41,6 +41,7 @@
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "SiteIconProvider.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
@ -55,17 +56,16 @@
#include "nsVoidArray.h"
#import "BookmarksService.h"
#import "StringUtils.h"
@implementation BookmarksDataSource
-(id) init
{
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
}
-(void) awakeFromNib
@ -86,16 +86,16 @@
-(void) ensureBookmarks
{
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
}
-(IBAction)addBookmark:(id)aSender
@ -530,20 +530,10 @@
//Get the cell of the text attachment.
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
//Figure out which image to add, and set the cell's image.
// Use the bookmark groups image for groups.
if ([self outlineView:outlineView isItemExpandable:item]) {
nsIContent* content = [item contentNode];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, BookmarksService::gGroupAtom, group);
if (!group.IsEmpty())
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"groupbookmark"]];
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]];
}
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
NSImage* bookmarkImage = mBookmarks->CreateIconForBookmark(elt);
[attachmentAttrStringCell setImage:bookmarkImage];
//Insert the image
[cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString];
@ -855,7 +845,16 @@
@end
#pragma mark -
@implementation BookmarkItem
-(void)dealloc
{
[mSiteIcon release];
[super dealloc];
}
-(nsIContent*)contentNode
{
return mContentNode;
@ -887,6 +886,18 @@
return [NSString stringWith_nsAString: href];
}
- (void)setSiteIcon:(NSImage*)image
{
//NSLog(@"Setting site icon for %@", [self url]);
[mSiteIcon autorelease];
mSiteIcon = [image retain];
}
- (NSImage*)siteIcon
{
return mSiteIcon;
}
-(void)setContentNode: (nsIContent*)aContentNode
{
mContentNode = aContentNode;
@ -896,6 +907,7 @@
{
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
[copy setContentNode: mContentNode];
[copy setSiteIcon: mSiteIcon];
return copy;
}

Просмотреть файл

@ -53,6 +53,9 @@ class nsIDOMHTMLDocument;
@class BookmarksDataSource;
@class BookmarkItem;
// despite appearances, BookmarksService is not a singleton. We make one for the bookmarks menu,
// one each per BookmarksDataSource, and one per bookmarks toolbar. It relies on a bunch of global
// variables, which is evil.
class BookmarksService
{
public:
@ -63,6 +66,7 @@ public:
void AddObserver();
void RemoveObserver();
public:
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
@ -71,7 +75,6 @@ public:
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
static void DeleteBookmark(nsIDOMElement* aBookmark);
public:
static void GetRootContent(nsIContent** aResult);
static BookmarkItem* GetRootItem();
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
@ -87,6 +90,8 @@ public:
static void ConstructAddBookmarkFolderList(NSPopUpButton* aPopup, BookmarkItem* aItem);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static void EnsureToolbarRoot();
static void ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc);
@ -96,8 +101,6 @@ public:
static NSString* ResolveKeyword(NSString* aKeyword);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
@ -139,3 +142,23 @@ private:
CHBookmarksToolbar* mToolbar;
BookmarksDataSource* mDataSource;
};
// singleton bookmarks manager object
@interface BookmarksManager : NSObject
{
}
+ (BookmarksManager*)sharedBookmarksManager;
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString;
@end

Просмотреть файл

@ -37,12 +37,13 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserView.h"
#import "BookmarksService.h"
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "CHIconTabViewItem.h"
#import "StringUtils.h"
#import "SiteIconProvider.h"
#include "nsCRT.h"
#include "nsString.h"
@ -106,6 +107,7 @@ NSMutableDictionary* BookmarksService::gDictionary = nil;
MainController* BookmarksService::gMainController = nil;
NSMenu* BookmarksService::gBookmarksMenu = nil;
nsIDOMElement* BookmarksService::gToolbarRoot = nsnull;
nsIAtom* BookmarksService::gBookmarkAtom = nsnull;
nsIAtom* BookmarksService::gDescriptionAtom = nsnull;
nsIAtom* BookmarksService::gFolderAtom = nsnull;
@ -114,8 +116,11 @@ nsIAtom* BookmarksService::gHrefAtom = nsnull;
nsIAtom* BookmarksService::gKeywordAtom = nsnull;
nsIAtom* BookmarksService::gNameAtom = nsnull;
nsIAtom* BookmarksService::gOpenAtom = nsnull;
nsVoidArray* BookmarksService::gInstances = nsnull;
BOOL BookmarksService::gBookmarksFileReadOK = NO;
int BookmarksService::CHInsertNone = 0;
int BookmarksService::CHInsertInto = 1;
int BookmarksService::CHInsertBefore = 2;
@ -137,6 +142,54 @@ BookmarksService::~BookmarksService()
{
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
#pragma mark -
void
BookmarksService::GetRootContent(nsIContent** aResult)
{
@ -211,7 +264,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
}
void
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -258,7 +311,7 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool
}
void
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -289,6 +342,10 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
aItem->GetAttr(kNameSpaceID_None, gNameAtom, name);
NSString* bookmarkTitle = [[NSString stringWith_nsAString: name] stringByTruncatingTo:80 at:kTruncateAtMiddle];
[childItem setTitle: bookmarkTitle];
// and reset the image
BookmarkItem* item = GetWrapperFor(aItem);
[childItem setImage: [item siteIcon]];
}
}
@ -298,7 +355,7 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
}
void
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances)
return;
@ -343,51 +400,6 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bo
FlushBookmarks();
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
void
BookmarksService::AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt)
@ -601,6 +613,40 @@ BookmarksService::FlushBookmarks()
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"groupbookmark"];
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
// fire off a proxy icon load
if ([[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL])
{
nsAutoString href;
content->GetAttr(kNameSpaceID_None, gHrefAtom, href);
if (href.Length() > 0)
{
BookmarkItem* contentItem = BookmarksService::GetWrapperFor(content);
if ([contentItem siteIcon])
return [contentItem siteIcon];
if (contentItem && ![contentItem siteIcon])
[[BookmarksManager sharedBookmarksManager] loadProxyImageFor:contentItem withURI:[NSString stringWith_nsAString:href]];
}
}
return [NSImage imageNamed:@"smallbookmark"];
}
void BookmarksService::EnsureToolbarRoot()
{
if (gToolbarRoot)
@ -763,18 +809,21 @@ BookmarksService::AddMenuBookmark(NSMenu* aMenu, nsIContent* aParent, nsIContent
nsAutoString group;
aChild->GetAttr(kNameSpaceID_None, gGroupAtom, group);
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aChild));
NSImage* menuItemImage = BookmarksService::CreateIconForBookmark(elt);
if (group.IsEmpty() && tagName == gFolderAtom) {
NSMenu* menu = [[[NSMenu alloc] initWithTitle: title] autorelease];
[aMenu setSubmenu: menu forItem: menuItem];
[menu setAutoenablesItems: NO];
[menuItem setImage: [NSImage imageNamed:@"folder"]];
[menuItem setImage: menuItemImage];
ConstructBookmarksMenu(menu, aChild);
}
else {
if (group.IsEmpty())
[menuItem setImage: [NSImage imageNamed:@"smallbookmark"]];
[menuItem setImage: menuItemImage];
else
[menuItem setImage: [NSImage imageNamed:@"groupbookmark"]];
[menuItem setImage: menuItemImage];
[menuItem setTarget: gMainController];
[menuItem setAction: @selector(openMenuBookmark:)];
@ -997,10 +1046,12 @@ BookmarksService::ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc)
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(bookmarksRoot));
nsCOMPtr<nsIContent> childContent(do_QueryInterface(importedRootElement));
#if 0
// XXX testing
if (gDictionary)
[gDictionary removeAllObjects];
#endif
// this will save the file
BookmarkAdded(parentContent, childContent, true /* flush */);
}
@ -1072,24 +1123,7 @@ BookmarksService::ResolveKeyword(NSString* aKeyword)
content->GetAttr(kNameSpaceID_None, gHrefAtom, url);
return [NSString stringWith_nsAString: url];
}
return [NSString stringWithCString:""];
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"smallgroup"];
return [NSImage imageNamed:@"groupbookmark"];
return [NSString string];
}
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
@ -1292,3 +1326,78 @@ BookmarksService::PerformURLDrop(BookmarkItem* parentItem, BookmarkItem* beforeI
return YES;
}
#pragma mark -
@interface BookmarksManager(Private)
- (void)registerNotificationListener;
- (void)imageLoadedNotification:(NSNotification*)notification;
@end
@implementation BookmarksManager
+ (BookmarksManager*)sharedBookmarksManager;
{
static BookmarksManager* sBookmarksManager = nil;
if (!sBookmarksManager)
sBookmarksManager = [[BookmarksManager alloc] init];
return sBookmarksManager;
}
- (id)init
{
if ((self = [super init]))
{
[self registerNotificationListener];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString
{
[[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon:self
forURI:inURIString withUserData:requestor allowNetwork:NO];
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// callback for [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon]
- (void)imageLoadedNotification:(NSNotification*)notification
{
//NSLog(@"BookmarksManager imageLoadedNotification");
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
id requestor = [userInfo objectForKey:SiteIconLoadUserDataKey]; // requestor is a BookmarkItem
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
if (iconImage && [requestor isMemberOfClass:[BookmarkItem class]])
{
[requestor setSiteIcon:iconImage];
BookmarksService::BookmarkChanged([requestor contentNode], FALSE);
}
}
}
@end

Просмотреть файл

@ -78,6 +78,7 @@ class nsIDOMNode;
@class BookmarksDataSource;
@class CHHistoryDataSource;
@class CHExtendedTabView;
@class CHPageProxyIcon;
@interface BrowserWindowController : NSWindowController<CHFind>
{
@ -93,6 +94,7 @@ class nsIDOMNode;
IBOutlet NSWindow* mLocationSheetWindow;
IBOutlet NSTextField* mLocationSheetURLField;
IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock
IBOutlet CHPageProxyIcon* mProxyIcon;
IBOutlet id mSidebarBrowserView; // currently unused
IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource;
@ -162,6 +164,7 @@ class nsIDOMNode;
- (void)loadURL:(NSString*)aURLSpec referrer:(NSString*)aReferrer activate:(BOOL)activate;
- (void)updateLocationFields:(NSString *)locationString;
- (void)updateSiteIcons:(NSImage *)siteIconImage;
- (void)updateToolbarItems;
- (void)focusURLBar;

Просмотреть файл

@ -46,6 +46,7 @@
#import "CHHistoryDataSource.h"
#import "CHExtendedTabView.h"
#import "CHUserDefaults.h"
#import "CHPageProxyIcon.h"
#include "nsIWebNavigation.h"
#include "nsIDOMElement.h"
@ -947,6 +948,13 @@ static NSArray* sToolbarDefaults = nil;
// [[self window] display];
}
- (void)updateSiteIcons:(NSImage *)siteIconImage
{
if (siteIconImage == nil)
siteIconImage = [NSImage imageNamed:@"globe_ico"];
[mProxyIcon setImage:siteIconImage];
}
-(void)newTab:(BOOL)allowHomepage
{
CHIconTabViewItem* newTab = [[[CHIconTabViewItem alloc] initWithIdentifier: nil] autorelease];

Просмотреть файл

@ -25,15 +25,20 @@
#import <Appkit/Appkit.h>
class nsIDOMElement;
class BookmarksService;
@class BookmarkItem;
@interface CHBookmarksButton : NSButton {
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BOOL mIsFolder;
@interface CHBookmarksButton : NSButton
{
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BookmarksService* mBookmarksService;
BOOL mIsFolder;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService;
-(void)setElement: (nsIDOMElement*)aElt;
-(nsIDOMElement*)element;

Просмотреть файл

@ -39,9 +39,9 @@
@implementation CHBookmarksButton
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mElement = nsnull;
[self setBezelStyle: NSRegularSquareBezelStyle];
[self setButtonType: NSMomentaryChangeButton];
[self setBordered: NO];
@ -52,6 +52,15 @@
return self;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService
{
if ( (self = [self initWithFrame:frame]) ) {
mBookmarksService = bookmarksService;
[self setElement:element];
}
return self;
}
-(IBAction)openBookmark:(id)aSender
{
// See if we're a group.
@ -203,22 +212,24 @@
nsAutoString tag;
mElement->GetLocalName(tag);
NSImage* bookmarkImage = mBookmarksService->CreateIconForBookmark(aElt);
nsAutoString group;
mElement->GetAttribute(NS_LITERAL_STRING("group"), group);
if (!group.IsEmpty()) {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"groupbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
}
else if (tag.Equals(NS_LITERAL_STRING("folder"))) {
[self setImage: [NSImage imageNamed: @"folder"]];
[self setImage: bookmarkImage];
mIsFolder = YES;
}
else {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"smallbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
nsAutoString href;

Просмотреть файл

@ -28,12 +28,13 @@ class nsIDOMElement;
class BookmarksService;
class CHBookmarksButton;
@interface CHBookmarksToolbar : NSView {
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
@interface CHBookmarksToolbar : NSView
{
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
CHBookmarksButton* mDragInsertionButton;
int mDragInsertionPosition;
BOOL mIsShowing;
int mDragInsertionPosition;
BOOL mIsShowing;
}
-(void)initializeToolbar;

Просмотреть файл

@ -31,9 +31,14 @@
#include "nsIDOMElement.h"
#include "nsIContent.h"
@interface CHBookmarksToolbar(Private)
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element;
@end
@implementation CHBookmarksToolbar
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mBookmarks = nsnull;
mButtons = [[NSMutableArray alloc] init];
@ -95,8 +100,7 @@
while (child) {
nsCOMPtr<nsIDOMElement> childElt(do_QueryInterface(child));
if (childElt) {
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: childElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:childElt];
[self addSubview: button];
[mButtons addObject: button];
}
@ -111,8 +115,7 @@
-(void)addButton: (nsIDOMElement*)aElt atIndex: (int)aIndex
{
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: aElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:aElt];
[self addSubview: button];
[mButtons insertObject: button atIndex: aIndex];
if ([self isShown])
@ -453,4 +456,9 @@
}
}
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element
{
return [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17) element:element bookmarksService:mBookmarks] autorelease];
}
@end

Просмотреть файл

@ -51,6 +51,9 @@
NSTabViewItem* mTab;
NSWindow* mWindow;
NSImage* mSiteIconImage; // current proxy icon image, which may be a site icon (favicon).
NSString* mSiteIconURI; // uri from which we loaded the site icon
// the secure state of this browser. We need to hold it so that we can set
// the global lock icon whenever we become the primary. Value is one of
// security enums in nsIWebProgressListener.
@ -60,9 +63,9 @@
NSString* mTitle;
CHBrowserView* mBrowserView;
NSString* defaultStatus;
NSString* loadingStatus;
ToolTip* toolTip;
NSString* mDefaultStatusString;
NSString* mLoadingStatusString;
ToolTip* mToolTip;
BOOL mIsPrimary;
BOOL mIsBusy;

Просмотреть файл

@ -37,9 +37,12 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserWrapper.h"
#import "BrowserWindowController.h"
#import "BookmarksService.h"
#import "SiteIconProvider.h"
#import "CHIconTabViewItem.h"
#import "ToolTip.h"
#include "nsCOMPtr.h"
@ -64,8 +67,18 @@
static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
const NSString* kOfflineNotificationName = @"offlineModeChanged";
@interface CHBrowserWrapper(Private)
-(void) setPendingActive:(BOOL)active;
- (void)setPendingActive:(BOOL)active;
- (void)registerNotificationListener;
- (void)setSiteIconImage:(NSImage*)inSiteIcon;
- (void)setSiteIconURI:(NSString*)inSiteIconURI;
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI;
@end
@implementation CHBrowserWrapper
@ -85,10 +98,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
#endif
[[NSNotificationCenter defaultCenter] removeObserver: self];
[defaultStatus release];
[loadingStatus release];
[toolTip release];
[mSiteIconImage release];
[mSiteIconURI release];
[mDefaultStatusString release];
[mLoadingStatusString release];
[mToolTip release];
[super dealloc];
}
@ -105,7 +120,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
progress = nil;
progressSuper = nil;
mIsPrimary = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kOfflineNotificationName object:nil];
[mBrowserView setActive: NO];
}
@ -133,7 +148,13 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mIsBusy = NO;
mListenersAttached = NO;
mSecureState = nsIWebProgressListener::STATE_IS_INSECURE;
toolTip = [[ToolTip alloc] init];
mToolTip = [[ToolTip alloc] init];
//[self setSiteIconImage:[NSImage imageNamed:@"globe_ico"]];
//[self setSiteIconURI: [NSString string]];
[self registerNotificationListener];
}
return self;
}
@ -155,9 +176,9 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (!mIsBusy)
[progress removeFromSuperview];
defaultStatus = NULL;
loadingStatus = DOCUMENT_DONE_STRING;
[status setStringValue:loadingStatus];
mDefaultStatusString = NULL;
mLoadingStatusString = DOCUMENT_DONE_STRING;
[status setStringValue:mLoadingStatusString];
mIsPrimary = YES;
@ -181,11 +202,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (mWindowController) // Only register if we're the content area.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(offlineModeChanged:)
name:@"offlineModeChanged"
name:kOfflineNotificationName
object:nil];
// Update the URL bar.
[mWindowController updateLocationFields:[self getCurrentURLSpec]];
[mWindowController updateSiteIcons:mSiteIconImage];
if (mWindowController && !mListenersAttached) {
mListenersAttached = YES;
@ -209,7 +231,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
return [mBrowserView getCurrentURLSpec];
}
- (void)awakeFromNib
- (void)awakeFromNib
{
}
@ -239,17 +261,17 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLoadingStarted
{
if (defaultStatus) {
[defaultStatus release];
defaultStatus = NULL;
if (mDefaultStatusString) {
[mDefaultStatusString release];
mDefaultStatusString = NULL;
}
[progressSuper addSubview:progress];
[progress setIndeterminate:YES];
[progress startAnimation:self];
loadingStatus = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:loadingStatus];
mLoadingStatusString = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:mLoadingStatusString];
mIsBusy = YES;
[mTab setLabel: NSLocalizedString(@"TabLoading", @"")];
@ -271,12 +293,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[progress stopAnimation:self];
[progress removeFromSuperview];
loadingStatus = DOCUMENT_DONE_STRING;
if (defaultStatus) {
[status setStringValue:defaultStatus];
mLoadingStatusString = DOCUMENT_DONE_STRING;
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
mIsBusy = NO;
@ -316,8 +338,32 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLocationChange:(NSString*)urlSpec
{
BOOL useSiteIcons = [[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL];
BOOL siteIconLoadInitiated = NO;
SiteIconProvider* faviconProvider = [SiteIconProvider sharedFavoriteIconProvider];
NSString* faviconURI = [SiteIconProvider faviconLocationStringFromURI:urlSpec];
if (useSiteIcons && [faviconURI length] > 0)
{
// if the favicon uri has changed, fire off favicon load. When it completes, our
// imageLoadedNotification selector gets called.
if (![faviconURI isEqualToString:mSiteIconURI])
siteIconLoadInitiated = [faviconProvider loadFavoriteIcon:self forURI:urlSpec withUserData:nil allowNetwork:YES];
}
else
{
if ([urlSpec isEqualToString:@"about:blank"])
faviconURI = urlSpec;
else
faviconURI = @"";
}
if (!siteIconLoadInitiated)
[self updateSiteIconImage:nil withURI:faviconURI];
if (mIsPrimary)
[mWindowController updateLocationFields:urlSpec];
[mWindowController updateLocationFields:urlSpec];
}
- (void)onStatusChange:(NSString*)aStatusString
@ -342,20 +388,20 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)setStatus:(NSString *)statusString ofType:(NSStatusType)type
{
if (type == NSStatusTypeScriptDefault) {
if (defaultStatus) {
[defaultStatus release];
if (mDefaultStatusString) {
[mDefaultStatusString release];
}
defaultStatus = statusString;
if (defaultStatus) {
[defaultStatus retain];
mDefaultStatusString = statusString;
if (mDefaultStatusString) {
[mDefaultStatusString retain];
}
}
else if (!statusString) {
if (defaultStatus) {
[status setStringValue:defaultStatus];
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
}
else {
@ -418,12 +464,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onShowTooltip:(NSPoint)where withText:(NSString*)text
{
NSPoint point = [[self window] convertBaseToScreen:[self convertPoint: where toView:nil]];
[toolTip showToolTipAtPoint: point withString: text];
[mToolTip showToolTipAtPoint: point withString: text];
}
- (void)onHideTooltip
{
[toolTip closeToolTip];
[mToolTip closeToolTip];
}
// Called when a context menu should be shown.
@ -547,4 +593,77 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mActivateOnLoad = active;
}
- (void)setSiteIconImage:(NSImage*)inSiteIcon
{
[mSiteIconImage autorelease];
mSiteIconImage = [inSiteIcon retain];
}
- (void)setSiteIconURI:(NSString*)inSiteIconURI
{
[mSiteIconURI autorelease];
mSiteIconURI = [inSiteIconURI retain];
}
// A nil inSiteIcon image indicates that we should use the default icon
// If inSiteIconURI is "about:blank", we don't show any icon
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI
{
BOOL resetTabIcon = NO;
if (![mSiteIconURI isEqualToString:inSiteIconURI])
{
if (!inSiteIcon)
{
if (![inSiteIconURI isEqualToString:@"about:blank"])
inSiteIcon = [NSImage imageNamed:@"globe_ico"];
}
[self setSiteIconImage: inSiteIcon];
[self setSiteIconURI: inSiteIconURI];
// update the proxy icon
if (mIsPrimary)
[mWindowController updateSiteIcons:mSiteIconImage];
resetTabIcon = YES;
}
// update the tab icon
if ([mTab isMemberOfClass:[CHIconTabViewItem class]])
{
CHIconTabViewItem* tabItem = (CHIconTabViewItem*)mTab;
if (resetTabIcon || ![tabItem tabIcon])
[tabItem setTabIcon:mSiteIconImage];
}
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// called when [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon] completes
- (void)imageLoadedNotification:(NSNotification*)notification
{
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
NSString* siteIconURI = [userInfo objectForKey:SiteIconLoadURIKey];
// NSLog(@"CHBrowserWrapper imageLoadedNotification got image %@ and uri %@", iconImage, proxyImageURI);
if (iconImage == nil)
siteIconURI = @""; // go back to default image
[self updateSiteIconImage:iconImage withURI:siteIconURI];
}
}
@end

Просмотреть файл

@ -40,7 +40,8 @@
#import <Cocoa/Cocoa.h>
@interface CHIconTabViewItem : NSTabViewItem {
@interface CHIconTabViewItem : NSTabViewItem
{
NSImage *mTabIcon;
NSDictionary* mLabelAttributes;
}

Просмотреть файл

@ -39,8 +39,9 @@
*
* ***** END LICENSE BLOCK ***** */
#import "CHIconTabViewItem.h"
#import "NSString+Utils.h"
#import "CHIconTabViewItem.h"
//
// NSParagraphStyle has a line break mode which will automatically
@ -91,7 +92,7 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
[labelParagraphStyle setLineBreakMode:NSLineBreakByTruncatingMiddle];
#endif
[labelParagraphStyle setAlignment:NSCenterTextAlignment];
[labelParagraphStyle setAlignment:NSNaturalTextAlignment];
NSFont *labelFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
mLabelAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
@ -139,9 +140,9 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
if ([self tabIcon]) {
NSPoint drawPoint = NSMakePoint( (tabRect.origin.x), (tabRect.origin.y + 15.0) );
[[self tabIcon] compositeToPoint:drawPoint operation:NSCompositeSourceOver];
tabRect = NSMakeRect(NSMinX(tabRect)+15.0,
tabRect = NSMakeRect(NSMinX(tabRect) + 18.0,
NSMinY(tabRect),
NSWidth(tabRect)-15.0,
NSWidth(tabRect) - 18.0,
NSHeight(tabRect));
}

Просмотреть файл

@ -25,7 +25,7 @@
@interface CHPageProxyIcon : NSImageView
{
}
@end

Просмотреть файл

@ -24,13 +24,25 @@
#import "NSString+Utils.h"
#import "CHPageProxyIcon.h"
#import "BookmarksService.h"
#import "MainController.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
#include "nsString.h"
@implementation CHPageProxyIcon
- (void)awakeFromNib
{
}
- (void)dealloc
{
[super dealloc];
}
- (void) resetCursorRects
{
NSCursor* cursor;
@ -77,4 +89,5 @@
event: event pasteboard: pboard source: self slideBack: YES];
}
@end

Просмотреть файл

@ -35,12 +35,16 @@
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <Carbon/Carbon.h>
@interface CHPreferenceManager : NSObject {
class nsIPref;
@interface CHPreferenceManager : NSObject
{
NSUserDefaults* mDefaults;
ICInstance mInternetConfig;
nsIPref* mPrefs;
}
+ (CHPreferenceManager *)sharedInstance;
@ -54,4 +58,9 @@
- (NSString *) getICStringPref:(ConstStr255Param) prefKey;
- (NSString *) homePage:(BOOL) checkStartupPagePref;
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
@end

Просмотреть файл

@ -86,8 +86,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (void) dealloc
{
::ICStop(mInternetConfig);
NS_IF_RELEASE(mPrefs);
nsresult rv;
ICStop (mInternetConfig);
nsCOMPtr<nsIPrefService> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
//NSLog(@"Saving prefs file");
@ -100,7 +102,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (BOOL) initInternetConfig
{
OSStatus error;
error = ICStart (&mInternetConfig, 'CHIM');
error = ::ICStart(&mInternetConfig, 'CHIM');
if (error != noErr) {
// XXX throw here?
NSLog(@"Error initializing IC");
@ -178,6 +180,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
return NO;
}
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
mPrefs = prefs;
NS_IF_ADDREF(mPrefs);
[self syncMozillaPrefs];
return YES;
}
@ -191,9 +197,8 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
char strbuf[1024];
int numbuf;
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs) {
// XXXw. throw?
if (!mPrefs) {
NSLog(@"Mozilla prefs not set up successfully");
return;
}
@ -201,42 +206,42 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// something that chimera can deal with.
PRInt32 acceptCookies = 0;
static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior";
prefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
mPrefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
if ( acceptCookies == 1 ) { // accept foreign cookies, assume off
acceptCookies = 2;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
else if ( acceptCookies == 3 ) { // p3p, assume all cookies on
acceptCookies = 0;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
// get proxies from SystemConfiguration
prefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
prefs->ClearUserPref("network.proxy.http");
prefs->ClearUserPref("network.proxy.http_port");
prefs->ClearUserPref("network.proxy.ssl");
prefs->ClearUserPref("network.proxy.ssl_port");
prefs->ClearUserPref("network.proxy.ftp");
prefs->ClearUserPref("network.proxy.ftp_port");
prefs->ClearUserPref("network.proxy.gopher");
prefs->ClearUserPref("network.proxy.gopher_port");
prefs->ClearUserPref("network.proxy.socks");
prefs->ClearUserPref("network.proxy.socks_port");
prefs->ClearUserPref("network.proxy.no_proxies_on");
mPrefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
mPrefs->ClearUserPref("network.proxy.http");
mPrefs->ClearUserPref("network.proxy.http_port");
mPrefs->ClearUserPref("network.proxy.ssl");
mPrefs->ClearUserPref("network.proxy.ssl_port");
mPrefs->ClearUserPref("network.proxy.ftp");
mPrefs->ClearUserPref("network.proxy.ftp_port");
mPrefs->ClearUserPref("network.proxy.gopher");
mPrefs->ClearUserPref("network.proxy.gopher_port");
mPrefs->ClearUserPref("network.proxy.socks");
mPrefs->ClearUserPref("network.proxy.socks_port");
mPrefs->ClearUserPref("network.proxy.no_proxies_on");
if ((cfDictionary = SCDynamicStoreCopyProxies (NULL)) != NULL) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPEnable, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.http", strbuf);
mPrefs->SetCharPref("network.proxy.http", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.http_port", numbuf);
mPrefs->SetIntPref("network.proxy.http_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -245,13 +250,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ssl", strbuf);
mPrefs->SetCharPref("network.proxy.ssl", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ssl_port", numbuf);
mPrefs->SetIntPref("network.proxy.ssl_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -260,13 +265,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ftp", strbuf);
mPrefs->SetCharPref("network.proxy.ftp", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ftp_port", numbuf);
mPrefs->SetIntPref("network.proxy.ftp_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -275,13 +280,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.gopher", strbuf);
mPrefs->SetCharPref("network.proxy.gopher", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.gopher_port", numbuf);
mPrefs->SetIntPref("network.proxy.gopher_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -290,13 +295,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.socks", strbuf);
mPrefs->SetCharPref("network.proxy.socks", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.socks_port", numbuf);
mPrefs->SetIntPref("network.proxy.socks_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -305,7 +310,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
cfString = CFStringCreateByCombiningStrings (NULL, cfArray, CFSTR(", "));
if (CFStringGetLength (cfString) > 0) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
mPrefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
}
}
}
@ -313,24 +318,73 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
}
}
// convenience routines for mozilla prefs
- (NSString*)getMozillaPrefString: (const char*)prefName
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
NSMutableString *prefValue = [[[NSMutableString alloc] init] autorelease];
NSString *prefValue = @"";
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs) {
char *buf = nsnull;
nsresult rv = prefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
[prefValue setString:[NSString stringWithCString:buf]];
free(buf);
}
char *buf = nsnull;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
// prefs are UTF-8
prefValue = [NSString stringWithUTF8String:buf];
free(buf);
if (outSuccess) *outSuccess = YES;
} else {
if (outSuccess) *outSuccess = NO;
}
return prefValue;
}
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
// colors are stored in HTML-like #FFFFFF strings
NSString* colorString = [self getStringPref:prefName withSuccess:outSuccess];
NSColor* returnColor = [NSColor blackColor];
if ([colorString hasPrefix:@"#"] && [colorString length] == 7)
{
unsigned int redInt, greenInt, blueInt;
sscanf([colorString cString], "#%02x%02x%02x", &redInt, &greenInt, &blueInt);
float redFloat = ((float)redInt / 255.0);
float greenFloat = ((float)greenInt / 255.0);
float blueFloat = ((float)blueInt / 255.0);
returnColor = [NSColor colorWithCalibratedRed:redFloat green:greenFloat blue:blueFloat alpha:1.0f];
}
return returnColor;
}
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRBool boolPref = PR_FALSE;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
rv = mPrefs->GetBoolPref(prefName, &boolPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return boolPref ? YES : NO;
}
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRInt32 intPref = 0;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetIntPref(prefName, &intPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return intPref;
}
//- (BOOL) getICBoolPref:(ConstStr255Param) prefKey;
//{
@ -381,8 +435,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (NSString *) homePage:(BOOL)checkStartupPagePref
{
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs)
if (!mPrefs)
return @"about:blank";
PRInt32 mode = 1;
@ -394,14 +447,14 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// is true.
nsresult rv = NS_OK;
if ( checkStartupPagePref )
rv = prefs->GetIntPref("browser.startup.page", &mode);
rv = mPrefs->GetIntPref("browser.startup.page", &mode);
if (NS_FAILED(rv) || mode == 1) {
// see which home page to use
PRBool boolPref;
if (NS_SUCCEEDED(prefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
if (NS_SUCCEEDED(mPrefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
return [self getICStringPref:kICWWWHomePage];
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefs);
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(mPrefs);
if (!prefBranch) return @"about:blank";
NSString* homepagePref = nil;
@ -411,10 +464,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
homepagePref = NSLocalizedStringFromTable( @"HomePageDefault", @"WebsiteDefaults", nil);
// and let's copy this into the homepage pref if it's not bad
if (![homepagePref isEqualToString:@"HomePageDefault"])
prefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
mPrefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
}
else {
homepagePref = [self getMozillaPrefString:"browser.startup.homepage"];
homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL];
}
if (homepagePref && [homepagePref length] > 0 && ![homepagePref isEqualToString:@"HomePageDefault"])

Просмотреть файл

@ -75,7 +75,7 @@ class BookmarksService;
FindDlgController* mFindDialog;
MVPreferencesController* preferencesController;
MVPreferencesController* mPreferencesController;
NSString* mStartURL;
}

Просмотреть файл

@ -132,7 +132,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[mBookmarksMenu setAutoenablesItems: NO];
mMenuBookmarks = new BookmarksService((BookmarksDataSource*)nil);
mMenuBookmarks->AddObserver();
mMenuBookmarks->ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::gMainController = self;
// Initialize offline mode.
@ -152,6 +152,29 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
*/
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferencesController release];
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
-(IBAction)newWindow:(id)aSender
{
// If we have a key window, have it autosave its dimensions before
@ -455,29 +478,6 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[[[controller getBrowserWrapper] getBrowserView] setActive: YES];
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
// Bookmarks menu actions.
-(IBAction) importBookmarks:(id)aSender
{
@ -558,10 +558,10 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (MVPreferencesController *)preferencesController
{
if (!preferencesController) {
preferencesController = [[MVPreferencesController sharedInstance] retain];
if (!mPreferencesController) {
mPreferencesController = [[MVPreferencesController sharedInstance] retain];
}
return preferencesController;
return mPreferencesController;
}
- (void)displayPreferencesWindow:sender

Просмотреть файл

@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
extern NSString* RemoteDataLoadRequestNotificationName;
extern NSString* RemoteDataLoadRequestURIKey;
extern NSString* RemoteDataLoadRequestDataKey;
extern NSString* RemoteDataLoadRequestUserDataKey;
extern NSString* RemoteDataLoadRequestResultKey;
// RemoteDataProvider is a class that can be used to do asynchronous loads
// from URIs using necko, and passing back the result of the load to a
// callback in NSData.
//
// Clients can either implement the RemoteLoadListener protocol and call
// loadURI directly, or they can register with the [NSNotification defaultCenter]
// for 'RemoteDataLoadRequestNotificationName' notifications, and catch all loads
// that happen that way.
@protocol RemoteLoadListener
// called when the load completes, or fails. If the status code is a failure code,
// data may be nil.
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status;
@end
class RemoteURILoadManager;
@interface RemoteDataProvider : NSObject<RemoteLoadListener>
{
RemoteURILoadManager* mLoadManager;
}
+ (RemoteDataProvider*)sharedRemoteDataProvider;
// generic method. You can load any URI asynchronously with this selector,
// and the listener will get the contents of the URI in an NSData.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
// specific request to load a remote file. The sender (or any other object), if
// registered with the notification center, will receive a notification when
// the load completes. The 'target' becomes the 'object' of the notification.
// The notification name is given by NSString* RemoteDataLoadRequestNotificationName above.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
@end

Просмотреть файл

@ -0,0 +1,298 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "RemoteDataProvider.h"
#include "nsISupports.h"
#include "nsHashtable.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* RemoteDataLoadRequestNotificationName = @"remoteload_notification_name";
NSString* RemoteDataLoadRequestURIKey = @"remoteload_uri_key";
NSString* RemoteDataLoadRequestDataKey = @"remoteload_data_key";
NSString* RemoteDataLoadRequestUserDataKey = @"remoteload_user_data_key";
NSString* RemoteDataLoadRequestResultKey = @"remoteload_result_key";
// this has to retain the load listener, to ensure that the listener lives long
// enough to receive notifications. We have to be careful to avoid ref cycles.
class StreamLoaderContext : public nsISupports
{
public:
StreamLoaderContext(id<RemoteLoadListener> inLoadListener, id inUserData, id inTarget, const nsAString& inURI)
: mLoadListener(inLoadListener)
, mTarget(inTarget)
, mUserData(inUserData)
, mURI(inURI)
{
NS_INIT_ISUPPORTS();
[mLoadListener retain];
}
virtual ~StreamLoaderContext()
{
[mLoadListener release];
}
NS_DECL_ISUPPORTS
void LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength);
const nsAString& GetURI() { return mURI; }
protected:
id<RemoteLoadListener> mLoadListener; // retained
id mTarget; // not retained
id mUserData; // not retained
nsString mURI;
};
NS_IMPL_ISUPPORTS1(StreamLoaderContext, nsISupports)
void StreamLoaderContext::LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength)
{
if (mLoadListener)
{
NSData* loadData = nil;
if (NS_SUCCEEDED(inLoadStatus))
loadData = [NSData dataWithBytes:inData length:inDataLength];
[mLoadListener doneRemoteLoad:[NSString stringWith_nsAString:mURI] forTarget:mTarget withUserData:mUserData data:loadData status:inLoadStatus];
}
}
class RemoteURILoadManager : public nsIStreamLoaderObserver
{
public:
RemoteURILoadManager();
virtual ~RemoteURILoadManager();
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
nsresult Init();
nsresult RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener, id userData, id target, PRBool allowNetworking);
protected:
nsSupportsHashtable mStreamLoaderHash; // hash of active stream loads, keyed on URI
nsCOMPtr<nsICacheSession> mCacheSession;
};
RemoteURILoadManager::RemoteURILoadManager()
{
NS_INIT_ISUPPORTS();
}
RemoteURILoadManager::~RemoteURILoadManager()
{
}
NS_IMPL_ISUPPORTS1(RemoteURILoadManager, nsIStreamLoaderObserver)
NS_IMETHODIMP RemoteURILoadManager::OnStreamComplete(nsIStreamLoader *loader, nsISupports *ctxt, nsresult status, PRUint32 resultLength, const char *result)
{
StreamLoaderContext* loaderContext = NS_STATIC_CAST(StreamLoaderContext*, ctxt);
if (loaderContext)
{
loaderContext->LoadComplete(status, (const void*)result, resultLength);
// remove the stream loader from the hash table
nsStringKey uriKey(loaderContext->GetURI());
PRBool removed = mStreamLoaderHash.Remove(&uriKey);
}
return NS_OK;
}
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
nsresult RemoteURILoadManager::Init()
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession("HTTP", nsICache::STORE_ANYWHERE,
nsICache::STREAM_BASED, getter_AddRefs(mCacheSession));
return rv;
}
nsresult RemoteURILoadManager::RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener,
id userData, id target, PRBool allowNetworking)
{
nsresult rv;
#if 0
// if no networking is allowed, make sure it's in the cache
if (!allowNetworking)
{
if (!mCacheSession)
return NS_ERROR_FAILURE;
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
rv = mCacheSession->OpenCacheEntry(NS_ConvertUCS2toUTF8(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc)
return NS_ERROR_FAILURE;
}
#endif
nsStringKey uriKey(inURI);
// first make sure that there isn't another entry in the hash for this
nsCOMPtr<nsISupports> foundStreamSupports = mStreamLoaderHash.Get(&uriKey);
if (foundStreamSupports)
return NS_OK;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), inURI);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsISupports> loaderContext = new StreamLoaderContext(loadListener, userData, target, inURI);
nsLoadFlags loadFlags = (allowNetworking) ? nsIRequest::LOAD_NORMAL : nsIRequest::LOAD_FROM_CACHE;
nsCOMPtr<nsIStreamLoader> streamLoader;
rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), uri, this, loaderContext, nsnull, nsnull, loadFlags);
if (NS_FAILED(rv))
{
NSLog(@"NS_NewStreamLoader for favicon failed");
return rv;
}
#ifdef DEBUG_smfr
NSLog(@"RequestURILoad called for %@", [NSString stringWith_nsAString: inURI]);
#endif
// put the stream loader into the hash table
nsCOMPtr<nsISupports> streamLoaderAsSupports = do_QueryInterface(streamLoader);
mStreamLoaderHash.Put(&uriKey, streamLoaderAsSupports);
return NS_OK;
}
#pragma mark -
@implementation RemoteDataProvider
+ (RemoteDataProvider*)sharedRemoteDataProvider
{
static RemoteDataProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[RemoteDataProvider alloc] init];
// we probably need to register for NSApplicationWillTerminateNotification notifications
// and delete this then.
}
return sIconProvider;
}
- (id)init
{
if ((self = [super init]))
{
mLoadManager = new RemoteURILoadManager;
NS_ADDREF(mLoadManager);
}
return self;
}
- (void)dealloc
{
NS_IF_RELEASE(mLoadManager);
[super dealloc];
}
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
//NSLog(@"loadURI called with %@", inURI);
if (mLoadManager && [inURI length] > 0)
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsresult rv = mLoadManager->RequestURILoad(uriString, inListener, userData, target, (PRBool)inNetworkOK);
if (NS_FAILED(rv))
{
NSLog(@"RequestURILoad failed for @%", inURI);
return NO;
}
}
return YES;
}
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
return [self loadURI:inURI forTarget:target withListener:self withUserData:userData allowNetworking:inNetworkOK];
}
// our own load listener callback
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, RemoteDataLoadRequestURIKey,
data, RemoteDataLoadRequestDataKey,
userData, RemoteDataLoadRequestUserDataKey,
[NSNumber numberWithInt:status], RemoteDataLoadRequestResultKey,
nil];
NSLog(@"remoteLoadDone with status %d and length %d", status, [data length]);
[[NSNotificationCenter defaultCenter] postNotificationName: RemoteDataLoadRequestNotificationName
object:target userInfo:notificationData];
}
@end

Просмотреть файл

@ -0,0 +1,69 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Cocoa/Cocoa.h>
#import "RemoteDataProvider.h"
extern NSString* SiteIconLoadNotificationName;
extern NSString* SiteIconLoadImageKey;
extern NSString* SiteIconLoadURIKey;
extern NSString* SiteIconLoadUserDataKey;
class NeckoCacheHelper;
@interface SiteIconProvider : NSObject<RemoteLoadListener>
{
NeckoCacheHelper* mMissedIconsCacheHelper;
}
+ (SiteIconProvider*)sharedFavoriteIconProvider;
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI;
// Start a favicon.ico load for the given URI, which can be any URI.
// The caller will get a 'SiteIconLoadNotificationName' notification
// when the load is done, with the image at the 'SiteIconLoadImageKey' key
// in the notifcation userInfo. The caller will have had to register with the
// NSNotifcationCenter in order to receive this notifcation. The notification
// is dispatched with 'sender' as the object.
// This method returns YES if the uri request was dispatched (i.e. if we know
// that we've looked for, and failed to find, this icon before). If it returns
// YES, then the 'SiteIconLoadNotificationName' notification will be sent out.
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork;
@end

330
chimera/SiteIconProvider.mm Normal file
Просмотреть файл

@ -0,0 +1,330 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "SiteIconProvider.h"
#include "prtime.h"
#include "nsString.h"
#include "nsISupports.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* SiteIconLoadNotificationName = @"siteicon_load_notification";
NSString* SiteIconLoadImageKey = @"siteicon_load_image";
NSString* SiteIconLoadURIKey = @"siteicon_load_uri";
NSString* SiteIconLoadUserDataKey = @"siteicon_load_user_data";
static inline PRUint32 PRTimeToSeconds(PRTime t_usec)
{
PRTime usec_per_sec;
PRUint32 t_sec;
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
LL_DIV(t_usec, t_usec, usec_per_sec);
LL_L2I(t_sec, t_usec);
return t_sec;
}
class NeckoCacheHelper
{
public:
NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue);
~NeckoCacheHelper() {}
nsresult Init(const char* inCacheSessionName);
nsresult ExistsInCache(const nsACString& inURI, PRBool* outExists);
nsresult PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds);
nsresult ClearCache();
protected:
const char* mMetaElement;
const char* mMetaValue;
nsCOMPtr<nsICacheSession> mCacheSession;
};
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
NeckoCacheHelper::NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue)
: mMetaElement(inMetaElement)
, mMetaValue(inMetaValue)
{
}
nsresult NeckoCacheHelper::Init(const char* inCacheSessionName)
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession(inCacheSessionName,
nsICache::STORE_ANYWHERE, nsICache::STREAM_BASED,
getter_AddRefs(mCacheSession));
if (NS_FAILED(rv))
return rv;
return NS_OK;
}
nsresult NeckoCacheHelper::ExistsInCache(const nsACString& inURI, PRBool* outExists)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
*outExists = NS_SUCCEEDED(rv) && (entryDesc != NULL);
return NS_OK;
}
nsresult NeckoCacheHelper::PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_WRITE, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc) return rv;
nsCacheAccessMode accessMode;
rv = entryDesc->GetAccessGranted(&accessMode);
if (NS_FAILED(rv))
return rv;
if (accessMode != nsICache::ACCESS_WRITE)
return NS_ERROR_FAILURE;
entryDesc->SetMetaDataElement(mMetaElement, mMetaValue); // just set a bit of meta data.
entryDesc->SetExpirationTime(PRTimeToSeconds(PR_Now()) + inExpirationTimeSeconds);
entryDesc->MarkValid();
entryDesc->Close();
return NS_OK;
}
nsresult NeckoCacheHelper::ClearCache()
{
NS_ASSERTION(mCacheSession, "No cache session");
return mCacheSession->EvictEntries();
}
#pragma mark -
static nsresult MakeFaviconURIFromURI(const nsAString& inURIString, nsAString& outFaviconURI)
{
outFaviconURI.Truncate(0);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), inURIString);
if (NS_FAILED(rv))
return rv;
// check for http/https
PRBool isHTTP = PR_FALSE, isHTTPS = PR_FALSE;
uri->SchemeIs("http", &isHTTP);
uri->SchemeIs("https", &isHTTPS);
if (!isHTTP && !isHTTPS)
return NS_OK;
PRInt32 port;
uri->GetPort(&port);
nsXPIDLCString scheme;
uri->GetScheme(scheme);
nsXPIDLCString host;
uri->GetHost(host);
nsCAutoString faviconURI = scheme;
faviconURI.Append("://");
faviconURI.Append(host);
if (port != -1) {
faviconURI.Append(':');
faviconURI.AppendInt(port);
}
faviconURI.Append("/favicon.ico");
outFaviconURI.Assign(NS_ConvertUTF8toUCS2(faviconURI));
return NS_OK;
}
@interface SiteIconProvider(Private)
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds;
- (BOOL)inMissedIconsCache:(const nsAString&)inURI;
@end
@implementation SiteIconProvider
- (id)init
{
if ((self = [super init]))
{
mMissedIconsCacheHelper = new NeckoCacheHelper("Favicon", "Missed");
nsresult rv = mMissedIconsCacheHelper->Init("MissedIconsCache");
if (NS_FAILED(rv)) {
delete mMissedIconsCacheHelper;
mMissedIconsCacheHelper = NULL;
}
}
return self;
}
- (void)dealloc
{
delete mMissedIconsCacheHelper;
[super dealloc];
}
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds
{
if (mMissedIconsCacheHelper)
{
nsresult rv = mMissedIconsCacheHelper->PutInCache(NS_ConvertUCS2toUTF8(inURI), inExpSeconds);
//NSLog(@"Putting %@ in missed icon cache", [NSString stringWith_nsAString:inURI]);
}
}
- (BOOL)inMissedIconsCache:(const nsAString&)inURI
{
PRBool inCache = PR_FALSE;
if (mMissedIconsCacheHelper)
mMissedIconsCacheHelper->ExistsInCache(NS_ConvertUCS2toUTF8(inURI), &inCache);
//NSLog(@"%@ in missed icon cache: %d", [NSString stringWith_nsAString:inURI], inCache);
return inCache;
}
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork
{
// look for a favicon
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
if (faviconURIString.Length() == 0)
return NO;
NSString* faviconString = [NSString stringWith_nsAString:faviconURIString];
// is this uri already in the missing icons cache?
if ([self inMissedIconsCache:faviconURIString])
return NO;
RemoteDataProvider* dataProvider = [RemoteDataProvider sharedRemoteDataProvider];
return [dataProvider loadURI:faviconString forTarget:sender withListener:self withUserData:userData allowNetworking:inAllowNetwork];
}
#define SITE_ICON_EXPIRATION_SECONDS (60 * 60 * 24 * 7) // 1 week
// this is called on the main thread
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
BOOL loadOK = NS_SUCCEEDED(status) && (data != nil);
// it's hard to tell if the favicon load succeeded or not. Even if the file
// does not exist, servers will send back a 404 page with a 0 status.
// So we just go ahead and try to make the image; it will return nil on
// failure.
NSImage* faviconImage = [[NSImage alloc] initWithData:data];
BOOL gotImageData = loadOK && (faviconImage != nil);
if (!gotImageData)
[self addToMissedIconsCache:uriString withExpirationSeconds:SITE_ICON_EXPIRATION_SECONDS];
[faviconImage setScalesWhenResized:YES];
[faviconImage setSize:NSMakeSize(16, 16)];
// we always send out the notification, so that clients know
// about failed requests
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, SiteIconLoadURIKey,
faviconImage, SiteIconLoadImageKey, // may be nil
userData, SiteIconLoadUserDataKey,
nil];
[[NSNotificationCenter defaultCenter] postNotificationName: SiteIconLoadNotificationName
object:target userInfo:notificationData];
}
#pragma mark -
+ (SiteIconProvider*)sharedFavoriteIconProvider
{
static SiteIconProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[SiteIconProvider alloc] init];
}
return sIconProvider;
}
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
return [NSString stringWith_nsAString:faviconURIString];
}
@end

Просмотреть файл

@ -75,7 +75,7 @@ class BookmarksService;
FindDlgController* mFindDialog;
MVPreferencesController* preferencesController;
MVPreferencesController* mPreferencesController;
NSString* mStartURL;
}

Просмотреть файл

@ -132,7 +132,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[mBookmarksMenu setAutoenablesItems: NO];
mMenuBookmarks = new BookmarksService((BookmarksDataSource*)nil);
mMenuBookmarks->AddObserver();
mMenuBookmarks->ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::ConstructBookmarksMenu(mBookmarksMenu, nsnull);
BookmarksService::gMainController = self;
// Initialize offline mode.
@ -152,6 +152,29 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
*/
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferencesController release];
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
-(IBAction)newWindow:(id)aSender
{
// If we have a key window, have it autosave its dimensions before
@ -455,29 +478,6 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[[[controller getBrowserWrapper] getBrowserView] setActive: YES];
}
-(void)applicationWillTerminate: (NSNotification*)aNotification
{
#if DEBUG
NSLog(@"Termination notification");
#endif
// Autosave one of the windows.
[[[mApplication mainWindow] windowController] autosaveWindowFrame];
mMenuBookmarks->RemoveObserver();
delete mMenuBookmarks;
mMenuBookmarks = nsnull;
// Release before calling TermEmbedding since we need to access XPCOM
// to save preferences
[mPreferenceManager release];
nsCocoaBrowserService::TermEmbedding();
[self autorelease];
}
// Bookmarks menu actions.
-(IBAction) importBookmarks:(id)aSender
{
@ -558,10 +558,10 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (MVPreferencesController *)preferencesController
{
if (!preferencesController) {
preferencesController = [[MVPreferencesController sharedInstance] retain];
if (!mPreferencesController) {
mPreferencesController = [[MVPreferencesController sharedInstance] retain];
}
return preferencesController;
return mPreferencesController;
}
- (void)displayPreferencesWindow:sender

Просмотреть файл

@ -25,15 +25,20 @@
#import <Appkit/Appkit.h>
class nsIDOMElement;
class BookmarksService;
@class BookmarkItem;
@interface CHBookmarksButton : NSButton {
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BOOL mIsFolder;
@interface CHBookmarksButton : NSButton
{
nsIDOMElement* mElement;
BookmarkItem* mBookmarkItem;
BookmarksService* mBookmarksService;
BOOL mIsFolder;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService;
-(void)setElement: (nsIDOMElement*)aElt;
-(nsIDOMElement*)element;

Просмотреть файл

@ -39,9 +39,9 @@
@implementation CHBookmarksButton
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mElement = nsnull;
[self setBezelStyle: NSRegularSquareBezelStyle];
[self setButtonType: NSMomentaryChangeButton];
[self setBordered: NO];
@ -52,6 +52,15 @@
return self;
}
-(id)initWithFrame:(NSRect)frame element:(nsIDOMElement*)element bookmarksService:(BookmarksService*)bookmarksService
{
if ( (self = [self initWithFrame:frame]) ) {
mBookmarksService = bookmarksService;
[self setElement:element];
}
return self;
}
-(IBAction)openBookmark:(id)aSender
{
// See if we're a group.
@ -203,22 +212,24 @@
nsAutoString tag;
mElement->GetLocalName(tag);
NSImage* bookmarkImage = mBookmarksService->CreateIconForBookmark(aElt);
nsAutoString group;
mElement->GetAttribute(NS_LITERAL_STRING("group"), group);
if (!group.IsEmpty()) {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"groupbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
}
else if (tag.Equals(NS_LITERAL_STRING("folder"))) {
[self setImage: [NSImage imageNamed: @"folder"]];
[self setImage: bookmarkImage];
mIsFolder = YES;
}
else {
mIsFolder = NO;
[self setImage: [NSImage imageNamed: @"smallbookmark"]];
[self setImage: bookmarkImage];
[self setAction: @selector(openBookmark:)];
[self setTarget: self];
nsAutoString href;

Просмотреть файл

@ -49,6 +49,7 @@ class BookmarksService;
@class BookmarkInfoController;
// data source for the bookmarks sidebar. We make one per browser window.
@interface BookmarksDataSource : NSObject
{
BookmarksService* mBookmarks;
@ -106,14 +107,16 @@ class BookmarksService;
@interface BookmarkItem : NSObject
{
nsIContent* mContentNode;
NSImage* mSiteIcon;
}
- (nsIContent*)contentNode;
- (void)setContentNode: (nsIContent*)aContentNode;
- (void)setSiteIcon:(NSImage*)image;
- (NSString*)url;
- (NSImage*)siteIcon;
- (NSNumber*)contentID;
- (id)copyWithZone:(NSZone *)aZone;
- (BOOL)isFolder;
@end

Просмотреть файл

@ -41,6 +41,7 @@
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "SiteIconProvider.h"
#include "nsCOMPtr.h"
#include "nsIContent.h"
@ -55,17 +56,16 @@
#include "nsVoidArray.h"
#import "BookmarksService.h"
#import "StringUtils.h"
@implementation BookmarksDataSource
-(id) init
{
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
if ( (self = [super init]) ) {
mBookmarks = nsnull;
mCachedHref = nil;
}
return self;
}
-(void) awakeFromNib
@ -86,16 +86,16 @@
-(void) ensureBookmarks
{
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
if (mBookmarks)
return;
mBookmarks = new BookmarksService(self);
mBookmarks->AddObserver();
[mOutlineView setTarget: self];
[mOutlineView setDoubleAction: @selector(openBookmark:)];
[mOutlineView setDeleteAction: @selector(deleteBookmarks:)];
[mOutlineView reloadData];
}
-(IBAction)addBookmark:(id)aSender
@ -530,20 +530,10 @@
//Get the cell of the text attachment.
attachmentAttrStringCell = (NSCell *)[(NSTextAttachment *)[attachmentAttrString attribute:NSAttachmentAttributeName atIndex:0 effectiveRange:nil] attachmentCell];
//Figure out which image to add, and set the cell's image.
// Use the bookmark groups image for groups.
if ([self outlineView:outlineView isItemExpandable:item]) {
nsIContent* content = [item contentNode];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, BookmarksService::gGroupAtom, group);
if (!group.IsEmpty())
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"groupbookmark"]];
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"folder"]];
}
else
[attachmentAttrStringCell setImage:[NSImage imageNamed:@"smallbookmark"]];
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(content));
NSImage* bookmarkImage = mBookmarks->CreateIconForBookmark(elt);
[attachmentAttrStringCell setImage:bookmarkImage];
//Insert the image
[cellValue replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attachmentAttrString];
@ -855,7 +845,16 @@
@end
#pragma mark -
@implementation BookmarkItem
-(void)dealloc
{
[mSiteIcon release];
[super dealloc];
}
-(nsIContent*)contentNode
{
return mContentNode;
@ -887,6 +886,18 @@
return [NSString stringWith_nsAString: href];
}
- (void)setSiteIcon:(NSImage*)image
{
//NSLog(@"Setting site icon for %@", [self url]);
[mSiteIcon autorelease];
mSiteIcon = [image retain];
}
- (NSImage*)siteIcon
{
return mSiteIcon;
}
-(void)setContentNode: (nsIContent*)aContentNode
{
mContentNode = aContentNode;
@ -896,6 +907,7 @@
{
BookmarkItem* copy = [[[self class] allocWithZone: aZone] init];
[copy setContentNode: mContentNode];
[copy setSiteIcon: mSiteIcon];
return copy;
}

Просмотреть файл

@ -53,6 +53,9 @@ class nsIDOMHTMLDocument;
@class BookmarksDataSource;
@class BookmarkItem;
// despite appearances, BookmarksService is not a singleton. We make one for the bookmarks menu,
// one each per BookmarksDataSource, and one per bookmarks toolbar. It relies on a bunch of global
// variables, which is evil.
class BookmarksService
{
public:
@ -63,6 +66,7 @@ public:
void AddObserver();
void RemoveObserver();
public:
static void BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
static void BookmarkChanged(nsIContent* aItem, bool shouldFlush = true);
static void BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true);
@ -71,7 +75,6 @@ public:
static void MoveBookmarkToFolder(nsIDOMElement* aBookmark, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt);
static void DeleteBookmark(nsIDOMElement* aBookmark);
public:
static void GetRootContent(nsIContent** aResult);
static BookmarkItem* GetRootItem();
static BookmarkItem* GetWrapperFor(nsIContent* aItem);
@ -87,6 +90,8 @@ public:
static void ConstructAddBookmarkFolderList(NSPopUpButton* aPopup, BookmarkItem* aItem);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static void EnsureToolbarRoot();
static void ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc);
@ -96,8 +101,6 @@ public:
static NSString* ResolveKeyword(NSString* aKeyword);
static NSImage* CreateIconForBookmark(nsIDOMElement* aElement);
static BOOL DoAncestorsIncludeNode(BookmarkItem* bookmark, BookmarkItem* searchItem);
static bool IsBookmarkDropValid(BookmarkItem* proposedParent, int index, NSArray* draggedIDs);
static bool PerformBookmarkDrop(BookmarkItem* parent, int index, NSArray* draggedIDs);
@ -139,3 +142,23 @@ private:
CHBookmarksToolbar* mToolbar;
BookmarksDataSource* mDataSource;
};
// singleton bookmarks manager object
@interface BookmarksManager : NSObject
{
}
+ (BookmarksManager*)sharedBookmarksManager;
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString;
@end

Просмотреть файл

@ -37,12 +37,13 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserView.h"
#import "BookmarksService.h"
#import "BookmarksDataSource.h"
#import "BookmarkInfoController.h"
#import "CHIconTabViewItem.h"
#import "StringUtils.h"
#import "SiteIconProvider.h"
#include "nsCRT.h"
#include "nsString.h"
@ -106,6 +107,7 @@ NSMutableDictionary* BookmarksService::gDictionary = nil;
MainController* BookmarksService::gMainController = nil;
NSMenu* BookmarksService::gBookmarksMenu = nil;
nsIDOMElement* BookmarksService::gToolbarRoot = nsnull;
nsIAtom* BookmarksService::gBookmarkAtom = nsnull;
nsIAtom* BookmarksService::gDescriptionAtom = nsnull;
nsIAtom* BookmarksService::gFolderAtom = nsnull;
@ -114,8 +116,11 @@ nsIAtom* BookmarksService::gHrefAtom = nsnull;
nsIAtom* BookmarksService::gKeywordAtom = nsnull;
nsIAtom* BookmarksService::gNameAtom = nsnull;
nsIAtom* BookmarksService::gOpenAtom = nsnull;
nsVoidArray* BookmarksService::gInstances = nsnull;
BOOL BookmarksService::gBookmarksFileReadOK = NO;
int BookmarksService::CHInsertNone = 0;
int BookmarksService::CHInsertInto = 1;
int BookmarksService::CHInsertBefore = 2;
@ -137,6 +142,54 @@ BookmarksService::~BookmarksService()
{
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
#pragma mark -
void
BookmarksService::GetRootContent(nsIContent** aResult)
{
@ -211,7 +264,7 @@ BookmarksService::LocateMenu(nsIContent* aContent)
}
void
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -258,7 +311,7 @@ BookmarksService::BookmarkAdded(nsIContent* aContainer, nsIContent* aChild, bool
}
void
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush)
{
if (!gInstances || !gDictionary)
return;
@ -289,6 +342,10 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
aItem->GetAttr(kNameSpaceID_None, gNameAtom, name);
NSString* bookmarkTitle = [[NSString stringWith_nsAString: name] stringByTruncatingTo:80 at:kTruncateAtMiddle];
[childItem setTitle: bookmarkTitle];
// and reset the image
BookmarkItem* item = GetWrapperFor(aItem);
[childItem setImage: [item siteIcon]];
}
}
@ -298,7 +355,7 @@ BookmarksService::BookmarkChanged(nsIContent* aItem, bool shouldFlush = true)
}
void
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush = true)
BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bool shouldFlush)
{
if (!gInstances)
return;
@ -343,51 +400,6 @@ BookmarksService::BookmarkRemoved(nsIContent* aContainer, nsIContent* aChild, bo
FlushBookmarks();
}
void
BookmarksService::AddObserver()
{
gRefCnt++;
if (gRefCnt == 1) {
gBookmarkAtom = NS_NewAtom("bookmark");
gFolderAtom = NS_NewAtom("folder");
gNameAtom = NS_NewAtom("name");
gHrefAtom = NS_NewAtom("href");
gOpenAtom = NS_NewAtom("open");
gKeywordAtom = NS_NewAtom("id");
gDescriptionAtom = NS_NewAtom("description");
gGroupAtom = NS_NewAtom("group");
gInstances = new nsVoidArray();
ReadBookmarks();
}
gInstances->AppendElement(this);
}
void
BookmarksService::RemoveObserver()
{
if (gRefCnt == 0)
return;
gInstances->RemoveElement(this);
gRefCnt--;
if (gRefCnt == 0) {
// Flush Bookmarks before shutting down as some changes are not flushed when
// they are performed (folder open/closed) as writing a whole bookmark file for
// that type of operation seems excessive.
FlushBookmarks();
NS_IF_RELEASE(gBookmarks);
NS_RELEASE(gBookmarkAtom);
NS_RELEASE(gFolderAtom);
NS_RELEASE(gNameAtom);
NS_RELEASE(gHrefAtom);
NS_RELEASE(gOpenAtom);
[gDictionary release];
}
}
void
BookmarksService::AddBookmarkToFolder(nsString& aURL, nsString& aTitle, nsIDOMElement* aFolder, nsIDOMElement* aBeforeElt)
@ -601,6 +613,40 @@ BookmarksService::FlushBookmarks()
domSerializer->SerializeToStream(domDoc, outputStream, nsnull);
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"groupbookmark"];
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
// fire off a proxy icon load
if ([[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL])
{
nsAutoString href;
content->GetAttr(kNameSpaceID_None, gHrefAtom, href);
if (href.Length() > 0)
{
BookmarkItem* contentItem = BookmarksService::GetWrapperFor(content);
if ([contentItem siteIcon])
return [contentItem siteIcon];
if (contentItem && ![contentItem siteIcon])
[[BookmarksManager sharedBookmarksManager] loadProxyImageFor:contentItem withURI:[NSString stringWith_nsAString:href]];
}
}
return [NSImage imageNamed:@"smallbookmark"];
}
void BookmarksService::EnsureToolbarRoot()
{
if (gToolbarRoot)
@ -763,18 +809,21 @@ BookmarksService::AddMenuBookmark(NSMenu* aMenu, nsIContent* aParent, nsIContent
nsAutoString group;
aChild->GetAttr(kNameSpaceID_None, gGroupAtom, group);
nsCOMPtr<nsIDOMElement> elt(do_QueryInterface(aChild));
NSImage* menuItemImage = BookmarksService::CreateIconForBookmark(elt);
if (group.IsEmpty() && tagName == gFolderAtom) {
NSMenu* menu = [[[NSMenu alloc] initWithTitle: title] autorelease];
[aMenu setSubmenu: menu forItem: menuItem];
[menu setAutoenablesItems: NO];
[menuItem setImage: [NSImage imageNamed:@"folder"]];
[menuItem setImage: menuItemImage];
ConstructBookmarksMenu(menu, aChild);
}
else {
if (group.IsEmpty())
[menuItem setImage: [NSImage imageNamed:@"smallbookmark"]];
[menuItem setImage: menuItemImage];
else
[menuItem setImage: [NSImage imageNamed:@"groupbookmark"]];
[menuItem setImage: menuItemImage];
[menuItem setTarget: gMainController];
[menuItem setAction: @selector(openMenuBookmark:)];
@ -997,10 +1046,12 @@ BookmarksService::ImportBookmarks(nsIDOMHTMLDocument* aHTMLDoc)
nsCOMPtr<nsIContent> parentContent(do_QueryInterface(bookmarksRoot));
nsCOMPtr<nsIContent> childContent(do_QueryInterface(importedRootElement));
#if 0
// XXX testing
if (gDictionary)
[gDictionary removeAllObjects];
#endif
// this will save the file
BookmarkAdded(parentContent, childContent, true /* flush */);
}
@ -1072,24 +1123,7 @@ BookmarksService::ResolveKeyword(NSString* aKeyword)
content->GetAttr(kNameSpaceID_None, gHrefAtom, url);
return [NSString stringWith_nsAString: url];
}
return [NSString stringWithCString:""];
}
NSImage*
BookmarksService::CreateIconForBookmark(nsIDOMElement* aElement)
{
nsCOMPtr<nsIAtom> tagName;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement);
content->GetTag(*getter_AddRefs(tagName));
if (tagName == BookmarksService::gFolderAtom)
return [NSImage imageNamed:@"folder"];
nsAutoString group;
content->GetAttr(kNameSpaceID_None, gGroupAtom, group);
if (!group.IsEmpty())
return [NSImage imageNamed:@"smallgroup"];
return [NSImage imageNamed:@"groupbookmark"];
return [NSString string];
}
// Is searchItem equal to bookmark or bookmark's parent, grandparent, etc?
@ -1292,3 +1326,78 @@ BookmarksService::PerformURLDrop(BookmarkItem* parentItem, BookmarkItem* beforeI
return YES;
}
#pragma mark -
@interface BookmarksManager(Private)
- (void)registerNotificationListener;
- (void)imageLoadedNotification:(NSNotification*)notification;
@end
@implementation BookmarksManager
+ (BookmarksManager*)sharedBookmarksManager;
{
static BookmarksManager* sBookmarksManager = nil;
if (!sBookmarksManager)
sBookmarksManager = [[BookmarksManager alloc] init];
return sBookmarksManager;
}
- (id)init
{
if ((self = [super init]))
{
[self registerNotificationListener];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (void)loadProxyImageFor:(id)requestor withURI:(NSString*)inURIString
{
[[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon:self
forURI:inURIString withUserData:requestor allowNetwork:NO];
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// callback for [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon]
- (void)imageLoadedNotification:(NSNotification*)notification
{
//NSLog(@"BookmarksManager imageLoadedNotification");
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
id requestor = [userInfo objectForKey:SiteIconLoadUserDataKey]; // requestor is a BookmarkItem
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
if (iconImage && [requestor isMemberOfClass:[BookmarkItem class]])
{
[requestor setSiteIcon:iconImage];
BookmarksService::BookmarkChanged([requestor contentNode], FALSE);
}
}
}
@end

Просмотреть файл

@ -28,12 +28,13 @@ class nsIDOMElement;
class BookmarksService;
class CHBookmarksButton;
@interface CHBookmarksToolbar : NSView {
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
@interface CHBookmarksToolbar : NSView
{
BookmarksService* mBookmarks;
NSMutableArray* mButtons;
CHBookmarksButton* mDragInsertionButton;
int mDragInsertionPosition;
BOOL mIsShowing;
int mDragInsertionPosition;
BOOL mIsShowing;
}
-(void)initializeToolbar;

Просмотреть файл

@ -31,9 +31,14 @@
#include "nsIDOMElement.h"
#include "nsIContent.h"
@interface CHBookmarksToolbar(Private)
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element;
@end
@implementation CHBookmarksToolbar
- (id)initWithFrame:(NSRect)frame {
- (id)initWithFrame:(NSRect)frame
{
if ( (self = [super initWithFrame:frame]) ) {
mBookmarks = nsnull;
mButtons = [[NSMutableArray alloc] init];
@ -95,8 +100,7 @@
while (child) {
nsCOMPtr<nsIDOMElement> childElt(do_QueryInterface(child));
if (childElt) {
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: childElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:childElt];
[self addSubview: button];
[mButtons addObject: button];
}
@ -111,8 +115,7 @@
-(void)addButton: (nsIDOMElement*)aElt atIndex: (int)aIndex
{
CHBookmarksButton* button = [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17)] autorelease];
[button setElement: aElt];
CHBookmarksButton* button = [self makeNewButtonWithElement:aElt];
[self addSubview: button];
[mButtons insertObject: button atIndex: aIndex];
if ([self isShown])
@ -453,4 +456,9 @@
}
}
- (CHBookmarksButton*)makeNewButtonWithElement:(nsIDOMElement*)element
{
return [[[CHBookmarksButton alloc] initWithFrame: NSMakeRect(2, 1, 100, 17) element:element bookmarksService:mBookmarks] autorelease];
}
@end

Просмотреть файл

@ -78,6 +78,7 @@ class nsIDOMNode;
@class BookmarksDataSource;
@class CHHistoryDataSource;
@class CHExtendedTabView;
@class CHPageProxyIcon;
@interface BrowserWindowController : NSWindowController<CHFind>
{
@ -93,6 +94,7 @@ class nsIDOMNode;
IBOutlet NSWindow* mLocationSheetWindow;
IBOutlet NSTextField* mLocationSheetURLField;
IBOutlet NSView* mStatusBar; // contains the status text, progress bar, and lock
IBOutlet CHPageProxyIcon* mProxyIcon;
IBOutlet id mSidebarBrowserView; // currently unused
IBOutlet BookmarksDataSource* mSidebarBookmarksDataSource;
@ -162,6 +164,7 @@ class nsIDOMNode;
- (void)loadURL:(NSString*)aURLSpec referrer:(NSString*)aReferrer activate:(BOOL)activate;
- (void)updateLocationFields:(NSString *)locationString;
- (void)updateSiteIcons:(NSImage *)siteIconImage;
- (void)updateToolbarItems;
- (void)focusURLBar;

Просмотреть файл

@ -46,6 +46,7 @@
#import "CHHistoryDataSource.h"
#import "CHExtendedTabView.h"
#import "CHUserDefaults.h"
#import "CHPageProxyIcon.h"
#include "nsIWebNavigation.h"
#include "nsIDOMElement.h"
@ -947,6 +948,13 @@ static NSArray* sToolbarDefaults = nil;
// [[self window] display];
}
- (void)updateSiteIcons:(NSImage *)siteIconImage
{
if (siteIconImage == nil)
siteIconImage = [NSImage imageNamed:@"globe_ico"];
[mProxyIcon setImage:siteIconImage];
}
-(void)newTab:(BOOL)allowHomepage
{
CHIconTabViewItem* newTab = [[[CHIconTabViewItem alloc] initWithIdentifier: nil] autorelease];

Просмотреть файл

@ -51,6 +51,9 @@
NSTabViewItem* mTab;
NSWindow* mWindow;
NSImage* mSiteIconImage; // current proxy icon image, which may be a site icon (favicon).
NSString* mSiteIconURI; // uri from which we loaded the site icon
// the secure state of this browser. We need to hold it so that we can set
// the global lock icon whenever we become the primary. Value is one of
// security enums in nsIWebProgressListener.
@ -60,9 +63,9 @@
NSString* mTitle;
CHBrowserView* mBrowserView;
NSString* defaultStatus;
NSString* loadingStatus;
ToolTip* toolTip;
NSString* mDefaultStatusString;
NSString* mLoadingStatusString;
ToolTip* mToolTip;
BOOL mIsPrimary;
BOOL mIsBusy;

Просмотреть файл

@ -37,9 +37,12 @@
#import "NSString+Utils.h"
#import "CHPreferenceManager.h"
#import "CHBrowserWrapper.h"
#import "BrowserWindowController.h"
#import "BookmarksService.h"
#import "SiteIconProvider.h"
#import "CHIconTabViewItem.h"
#import "ToolTip.h"
#include "nsCOMPtr.h"
@ -64,8 +67,18 @@
static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
const NSString* kOfflineNotificationName = @"offlineModeChanged";
@interface CHBrowserWrapper(Private)
-(void) setPendingActive:(BOOL)active;
- (void)setPendingActive:(BOOL)active;
- (void)registerNotificationListener;
- (void)setSiteIconImage:(NSImage*)inSiteIcon;
- (void)setSiteIconURI:(NSString*)inSiteIconURI;
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI;
@end
@implementation CHBrowserWrapper
@ -85,10 +98,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
#endif
[[NSNotificationCenter defaultCenter] removeObserver: self];
[defaultStatus release];
[loadingStatus release];
[toolTip release];
[mSiteIconImage release];
[mSiteIconURI release];
[mDefaultStatusString release];
[mLoadingStatusString release];
[mToolTip release];
[super dealloc];
}
@ -105,7 +120,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
progress = nil;
progressSuper = nil;
mIsPrimary = NO;
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] removeObserver:self name:kOfflineNotificationName object:nil];
[mBrowserView setActive: NO];
}
@ -133,7 +148,13 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mIsBusy = NO;
mListenersAttached = NO;
mSecureState = nsIWebProgressListener::STATE_IS_INSECURE;
toolTip = [[ToolTip alloc] init];
mToolTip = [[ToolTip alloc] init];
//[self setSiteIconImage:[NSImage imageNamed:@"globe_ico"]];
//[self setSiteIconURI: [NSString string]];
[self registerNotificationListener];
}
return self;
}
@ -155,9 +176,9 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (!mIsBusy)
[progress removeFromSuperview];
defaultStatus = NULL;
loadingStatus = DOCUMENT_DONE_STRING;
[status setStringValue:loadingStatus];
mDefaultStatusString = NULL;
mLoadingStatusString = DOCUMENT_DONE_STRING;
[status setStringValue:mLoadingStatusString];
mIsPrimary = YES;
@ -181,11 +202,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
if (mWindowController) // Only register if we're the content area.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(offlineModeChanged:)
name:@"offlineModeChanged"
name:kOfflineNotificationName
object:nil];
// Update the URL bar.
[mWindowController updateLocationFields:[self getCurrentURLSpec]];
[mWindowController updateSiteIcons:mSiteIconImage];
if (mWindowController && !mListenersAttached) {
mListenersAttached = YES;
@ -209,7 +231,7 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
return [mBrowserView getCurrentURLSpec];
}
- (void)awakeFromNib
- (void)awakeFromNib
{
}
@ -239,17 +261,17 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLoadingStarted
{
if (defaultStatus) {
[defaultStatus release];
defaultStatus = NULL;
if (mDefaultStatusString) {
[mDefaultStatusString release];
mDefaultStatusString = NULL;
}
[progressSuper addSubview:progress];
[progress setIndeterminate:YES];
[progress startAnimation:self];
loadingStatus = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:loadingStatus];
mLoadingStatusString = NSLocalizedString(@"TabLoading", @"");
[status setStringValue:mLoadingStatusString];
mIsBusy = YES;
[mTab setLabel: NSLocalizedString(@"TabLoading", @"")];
@ -271,12 +293,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
[progress stopAnimation:self];
[progress removeFromSuperview];
loadingStatus = DOCUMENT_DONE_STRING;
if (defaultStatus) {
[status setStringValue:defaultStatus];
mLoadingStatusString = DOCUMENT_DONE_STRING;
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
mIsBusy = NO;
@ -316,8 +338,32 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onLocationChange:(NSString*)urlSpec
{
BOOL useSiteIcons = [[CHPreferenceManager sharedInstance] getBooleanPref:"browser.chrome.site_icons" withSuccess:NULL];
BOOL siteIconLoadInitiated = NO;
SiteIconProvider* faviconProvider = [SiteIconProvider sharedFavoriteIconProvider];
NSString* faviconURI = [SiteIconProvider faviconLocationStringFromURI:urlSpec];
if (useSiteIcons && [faviconURI length] > 0)
{
// if the favicon uri has changed, fire off favicon load. When it completes, our
// imageLoadedNotification selector gets called.
if (![faviconURI isEqualToString:mSiteIconURI])
siteIconLoadInitiated = [faviconProvider loadFavoriteIcon:self forURI:urlSpec withUserData:nil allowNetwork:YES];
}
else
{
if ([urlSpec isEqualToString:@"about:blank"])
faviconURI = urlSpec;
else
faviconURI = @"";
}
if (!siteIconLoadInitiated)
[self updateSiteIconImage:nil withURI:faviconURI];
if (mIsPrimary)
[mWindowController updateLocationFields:urlSpec];
[mWindowController updateLocationFields:urlSpec];
}
- (void)onStatusChange:(NSString*)aStatusString
@ -342,20 +388,20 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)setStatus:(NSString *)statusString ofType:(NSStatusType)type
{
if (type == NSStatusTypeScriptDefault) {
if (defaultStatus) {
[defaultStatus release];
if (mDefaultStatusString) {
[mDefaultStatusString release];
}
defaultStatus = statusString;
if (defaultStatus) {
[defaultStatus retain];
mDefaultStatusString = statusString;
if (mDefaultStatusString) {
[mDefaultStatusString retain];
}
}
else if (!statusString) {
if (defaultStatus) {
[status setStringValue:defaultStatus];
if (mDefaultStatusString) {
[status setStringValue:mDefaultStatusString];
}
else {
[status setStringValue:loadingStatus];
[status setStringValue:mLoadingStatusString];
}
}
else {
@ -418,12 +464,12 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
- (void)onShowTooltip:(NSPoint)where withText:(NSString*)text
{
NSPoint point = [[self window] convertBaseToScreen:[self convertPoint: where toView:nil]];
[toolTip showToolTipAtPoint: point withString: text];
[mToolTip showToolTipAtPoint: point withString: text];
}
- (void)onHideTooltip
{
[toolTip closeToolTip];
[mToolTip closeToolTip];
}
// Called when a context menu should be shown.
@ -547,4 +593,77 @@ static const char* ioServiceContractID = "@mozilla.org/network/io-service;1";
mActivateOnLoad = active;
}
- (void)setSiteIconImage:(NSImage*)inSiteIcon
{
[mSiteIconImage autorelease];
mSiteIconImage = [inSiteIcon retain];
}
- (void)setSiteIconURI:(NSString*)inSiteIconURI
{
[mSiteIconURI autorelease];
mSiteIconURI = [inSiteIconURI retain];
}
// A nil inSiteIcon image indicates that we should use the default icon
// If inSiteIconURI is "about:blank", we don't show any icon
- (void)updateSiteIconImage:(NSImage*)inSiteIcon withURI:(NSString *)inSiteIconURI
{
BOOL resetTabIcon = NO;
if (![mSiteIconURI isEqualToString:inSiteIconURI])
{
if (!inSiteIcon)
{
if (![inSiteIconURI isEqualToString:@"about:blank"])
inSiteIcon = [NSImage imageNamed:@"globe_ico"];
}
[self setSiteIconImage: inSiteIcon];
[self setSiteIconURI: inSiteIconURI];
// update the proxy icon
if (mIsPrimary)
[mWindowController updateSiteIcons:mSiteIconImage];
resetTabIcon = YES;
}
// update the tab icon
if ([mTab isMemberOfClass:[CHIconTabViewItem class]])
{
CHIconTabViewItem* tabItem = (CHIconTabViewItem*)mTab;
if (resetTabIcon || ![tabItem tabIcon])
[tabItem setTabIcon:mSiteIconImage];
}
}
- (void)registerNotificationListener
{
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(imageLoadedNotification:)
name: SiteIconLoadNotificationName
object: self];
}
// called when [[SiteIconProvider sharedFavoriteIconProvider] loadFavoriteIcon] completes
- (void)imageLoadedNotification:(NSNotification*)notification
{
NSDictionary* userInfo = [notification userInfo];
if (userInfo)
{
NSImage* iconImage = [userInfo objectForKey:SiteIconLoadImageKey];
NSString* siteIconURI = [userInfo objectForKey:SiteIconLoadURIKey];
// NSLog(@"CHBrowserWrapper imageLoadedNotification got image %@ and uri %@", iconImage, proxyImageURI);
if (iconImage == nil)
siteIconURI = @""; // go back to default image
[self updateSiteIconImage:iconImage withURI:siteIconURI];
}
}
@end

Просмотреть файл

@ -25,7 +25,7 @@
@interface CHPageProxyIcon : NSImageView
{
}
@end

Просмотреть файл

@ -24,13 +24,25 @@
#import "NSString+Utils.h"
#import "CHPageProxyIcon.h"
#import "BookmarksService.h"
#import "MainController.h"
#include "nsCRT.h"
#include "nsNetUtil.h"
#include "nsString.h"
@implementation CHPageProxyIcon
- (void)awakeFromNib
{
}
- (void)dealloc
{
[super dealloc];
}
- (void) resetCursorRects
{
NSCursor* cursor;
@ -77,4 +89,5 @@
event: event pasteboard: pboard source: self slideBack: YES];
}
@end

Просмотреть файл

@ -0,0 +1,90 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
extern NSString* RemoteDataLoadRequestNotificationName;
extern NSString* RemoteDataLoadRequestURIKey;
extern NSString* RemoteDataLoadRequestDataKey;
extern NSString* RemoteDataLoadRequestUserDataKey;
extern NSString* RemoteDataLoadRequestResultKey;
// RemoteDataProvider is a class that can be used to do asynchronous loads
// from URIs using necko, and passing back the result of the load to a
// callback in NSData.
//
// Clients can either implement the RemoteLoadListener protocol and call
// loadURI directly, or they can register with the [NSNotification defaultCenter]
// for 'RemoteDataLoadRequestNotificationName' notifications, and catch all loads
// that happen that way.
@protocol RemoteLoadListener
// called when the load completes, or fails. If the status code is a failure code,
// data may be nil.
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status;
@end
class RemoteURILoadManager;
@interface RemoteDataProvider : NSObject<RemoteLoadListener>
{
RemoteURILoadManager* mLoadManager;
}
+ (RemoteDataProvider*)sharedRemoteDataProvider;
// generic method. You can load any URI asynchronously with this selector,
// and the listener will get the contents of the URI in an NSData.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
// specific request to load a remote file. The sender (or any other object), if
// registered with the notification center, will receive a notification when
// the load completes. The 'target' becomes the 'object' of the notification.
// The notification name is given by NSString* RemoteDataLoadRequestNotificationName above.
// If allowNetworking is NO, then this method will just check the cache,
// and not go to the network
// This method will return YES if the request was dispatched, or NO otherwise.
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK;
@end

Просмотреть файл

@ -0,0 +1,298 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "RemoteDataProvider.h"
#include "nsISupports.h"
#include "nsHashtable.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* RemoteDataLoadRequestNotificationName = @"remoteload_notification_name";
NSString* RemoteDataLoadRequestURIKey = @"remoteload_uri_key";
NSString* RemoteDataLoadRequestDataKey = @"remoteload_data_key";
NSString* RemoteDataLoadRequestUserDataKey = @"remoteload_user_data_key";
NSString* RemoteDataLoadRequestResultKey = @"remoteload_result_key";
// this has to retain the load listener, to ensure that the listener lives long
// enough to receive notifications. We have to be careful to avoid ref cycles.
class StreamLoaderContext : public nsISupports
{
public:
StreamLoaderContext(id<RemoteLoadListener> inLoadListener, id inUserData, id inTarget, const nsAString& inURI)
: mLoadListener(inLoadListener)
, mTarget(inTarget)
, mUserData(inUserData)
, mURI(inURI)
{
NS_INIT_ISUPPORTS();
[mLoadListener retain];
}
virtual ~StreamLoaderContext()
{
[mLoadListener release];
}
NS_DECL_ISUPPORTS
void LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength);
const nsAString& GetURI() { return mURI; }
protected:
id<RemoteLoadListener> mLoadListener; // retained
id mTarget; // not retained
id mUserData; // not retained
nsString mURI;
};
NS_IMPL_ISUPPORTS1(StreamLoaderContext, nsISupports)
void StreamLoaderContext::LoadComplete(nsresult inLoadStatus, const void* inData, unsigned int inDataLength)
{
if (mLoadListener)
{
NSData* loadData = nil;
if (NS_SUCCEEDED(inLoadStatus))
loadData = [NSData dataWithBytes:inData length:inDataLength];
[mLoadListener doneRemoteLoad:[NSString stringWith_nsAString:mURI] forTarget:mTarget withUserData:mUserData data:loadData status:inLoadStatus];
}
}
class RemoteURILoadManager : public nsIStreamLoaderObserver
{
public:
RemoteURILoadManager();
virtual ~RemoteURILoadManager();
NS_DECL_ISUPPORTS
NS_DECL_NSISTREAMLOADEROBSERVER
nsresult Init();
nsresult RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener, id userData, id target, PRBool allowNetworking);
protected:
nsSupportsHashtable mStreamLoaderHash; // hash of active stream loads, keyed on URI
nsCOMPtr<nsICacheSession> mCacheSession;
};
RemoteURILoadManager::RemoteURILoadManager()
{
NS_INIT_ISUPPORTS();
}
RemoteURILoadManager::~RemoteURILoadManager()
{
}
NS_IMPL_ISUPPORTS1(RemoteURILoadManager, nsIStreamLoaderObserver)
NS_IMETHODIMP RemoteURILoadManager::OnStreamComplete(nsIStreamLoader *loader, nsISupports *ctxt, nsresult status, PRUint32 resultLength, const char *result)
{
StreamLoaderContext* loaderContext = NS_STATIC_CAST(StreamLoaderContext*, ctxt);
if (loaderContext)
{
loaderContext->LoadComplete(status, (const void*)result, resultLength);
// remove the stream loader from the hash table
nsStringKey uriKey(loaderContext->GetURI());
PRBool removed = mStreamLoaderHash.Remove(&uriKey);
}
return NS_OK;
}
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
nsresult RemoteURILoadManager::Init()
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession("HTTP", nsICache::STORE_ANYWHERE,
nsICache::STREAM_BASED, getter_AddRefs(mCacheSession));
return rv;
}
nsresult RemoteURILoadManager::RequestURILoad(const nsAString& inURI, id<RemoteLoadListener> loadListener,
id userData, id target, PRBool allowNetworking)
{
nsresult rv;
#if 0
// if no networking is allowed, make sure it's in the cache
if (!allowNetworking)
{
if (!mCacheSession)
return NS_ERROR_FAILURE;
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
rv = mCacheSession->OpenCacheEntry(NS_ConvertUCS2toUTF8(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc)
return NS_ERROR_FAILURE;
}
#endif
nsStringKey uriKey(inURI);
// first make sure that there isn't another entry in the hash for this
nsCOMPtr<nsISupports> foundStreamSupports = mStreamLoaderHash.Get(&uriKey);
if (foundStreamSupports)
return NS_OK;
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), inURI);
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsISupports> loaderContext = new StreamLoaderContext(loadListener, userData, target, inURI);
nsLoadFlags loadFlags = (allowNetworking) ? nsIRequest::LOAD_NORMAL : nsIRequest::LOAD_FROM_CACHE;
nsCOMPtr<nsIStreamLoader> streamLoader;
rv = NS_NewStreamLoader(getter_AddRefs(streamLoader), uri, this, loaderContext, nsnull, nsnull, loadFlags);
if (NS_FAILED(rv))
{
NSLog(@"NS_NewStreamLoader for favicon failed");
return rv;
}
#ifdef DEBUG_smfr
NSLog(@"RequestURILoad called for %@", [NSString stringWith_nsAString: inURI]);
#endif
// put the stream loader into the hash table
nsCOMPtr<nsISupports> streamLoaderAsSupports = do_QueryInterface(streamLoader);
mStreamLoaderHash.Put(&uriKey, streamLoaderAsSupports);
return NS_OK;
}
#pragma mark -
@implementation RemoteDataProvider
+ (RemoteDataProvider*)sharedRemoteDataProvider
{
static RemoteDataProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[RemoteDataProvider alloc] init];
// we probably need to register for NSApplicationWillTerminateNotification notifications
// and delete this then.
}
return sIconProvider;
}
- (id)init
{
if ((self = [super init]))
{
mLoadManager = new RemoteURILoadManager;
NS_ADDREF(mLoadManager);
}
return self;
}
- (void)dealloc
{
NS_IF_RELEASE(mLoadManager);
[super dealloc];
}
- (BOOL)loadURI:(NSString*)inURI forTarget:(id)target withListener:(id<RemoteLoadListener>)inListener
withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
//NSLog(@"loadURI called with %@", inURI);
if (mLoadManager && [inURI length] > 0)
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsresult rv = mLoadManager->RequestURILoad(uriString, inListener, userData, target, (PRBool)inNetworkOK);
if (NS_FAILED(rv))
{
NSLog(@"RequestURILoad failed for @%", inURI);
return NO;
}
}
return YES;
}
- (BOOL)postURILoadRequest:(NSString*)inURI forTarget:(id)target withUserData:(id)userData allowNetworking:(BOOL)inNetworkOK
{
return [self loadURI:inURI forTarget:target withListener:self withUserData:userData allowNetworking:inNetworkOK];
}
// our own load listener callback
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, RemoteDataLoadRequestURIKey,
data, RemoteDataLoadRequestDataKey,
userData, RemoteDataLoadRequestUserDataKey,
[NSNumber numberWithInt:status], RemoteDataLoadRequestResultKey,
nil];
NSLog(@"remoteLoadDone with status %d and length %d", status, [data length]);
[[NSNotificationCenter defaultCenter] postNotificationName: RemoteDataLoadRequestNotificationName
object:target userInfo:notificationData];
}
@end

Просмотреть файл

@ -0,0 +1,69 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import <Cocoa/Cocoa.h>
#import "RemoteDataProvider.h"
extern NSString* SiteIconLoadNotificationName;
extern NSString* SiteIconLoadImageKey;
extern NSString* SiteIconLoadURIKey;
extern NSString* SiteIconLoadUserDataKey;
class NeckoCacheHelper;
@interface SiteIconProvider : NSObject<RemoteLoadListener>
{
NeckoCacheHelper* mMissedIconsCacheHelper;
}
+ (SiteIconProvider*)sharedFavoriteIconProvider;
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI;
// Start a favicon.ico load for the given URI, which can be any URI.
// The caller will get a 'SiteIconLoadNotificationName' notification
// when the load is done, with the image at the 'SiteIconLoadImageKey' key
// in the notifcation userInfo. The caller will have had to register with the
// NSNotifcationCenter in order to receive this notifcation. The notification
// is dispatched with 'sender' as the object.
// This method returns YES if the uri request was dispatched (i.e. if we know
// that we've looked for, and failed to find, this icon before). If it returns
// YES, then the 'SiteIconLoadNotificationName' notification will be sent out.
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork;
@end

Просмотреть файл

@ -0,0 +1,330 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Chimera code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2002
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Simon Fraser <sfraser@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#import "NSString+Utils.h"
#import "SiteIconProvider.h"
#include "prtime.h"
#include "nsString.h"
#include "nsISupports.h"
#include "nsNetUtil.h"
#include "nsICacheSession.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
NSString* SiteIconLoadNotificationName = @"siteicon_load_notification";
NSString* SiteIconLoadImageKey = @"siteicon_load_image";
NSString* SiteIconLoadURIKey = @"siteicon_load_uri";
NSString* SiteIconLoadUserDataKey = @"siteicon_load_user_data";
static inline PRUint32 PRTimeToSeconds(PRTime t_usec)
{
PRTime usec_per_sec;
PRUint32 t_sec;
LL_I2L(usec_per_sec, PR_USEC_PER_SEC);
LL_DIV(t_usec, t_usec, usec_per_sec);
LL_L2I(t_sec, t_usec);
return t_sec;
}
class NeckoCacheHelper
{
public:
NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue);
~NeckoCacheHelper() {}
nsresult Init(const char* inCacheSessionName);
nsresult ExistsInCache(const nsACString& inURI, PRBool* outExists);
nsresult PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds);
nsresult ClearCache();
protected:
const char* mMetaElement;
const char* mMetaValue;
nsCOMPtr<nsICacheSession> mCacheSession;
};
static NS_DEFINE_CID(kCacheServiceCID, NS_CACHESERVICE_CID);
NeckoCacheHelper::NeckoCacheHelper(const char* inMetaElement, const char* inMetaValue)
: mMetaElement(inMetaElement)
, mMetaValue(inMetaValue)
{
}
nsresult NeckoCacheHelper::Init(const char* inCacheSessionName)
{
nsresult rv;
nsCOMPtr<nsICacheService> cacheService = do_GetService(kCacheServiceCID, &rv);
if (NS_FAILED(rv))
return rv;
rv = cacheService->CreateSession(inCacheSessionName,
nsICache::STORE_ANYWHERE, nsICache::STREAM_BASED,
getter_AddRefs(mCacheSession));
if (NS_FAILED(rv))
return rv;
return NS_OK;
}
nsresult NeckoCacheHelper::ExistsInCache(const nsACString& inURI, PRBool* outExists)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_READ, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
*outExists = NS_SUCCEEDED(rv) && (entryDesc != NULL);
return NS_OK;
}
nsresult NeckoCacheHelper::PutInCache(const nsACString& inURI, PRUint32 inExpirationTimeSeconds)
{
NS_ASSERTION(mCacheSession, "No cache session");
nsCOMPtr<nsICacheEntryDescriptor> entryDesc;
nsresult rv = mCacheSession->OpenCacheEntry(PromiseFlatCString(inURI).get(), nsICache::ACCESS_WRITE, nsICache::NON_BLOCKING, getter_AddRefs(entryDesc));
if (NS_FAILED(rv) || !entryDesc) return rv;
nsCacheAccessMode accessMode;
rv = entryDesc->GetAccessGranted(&accessMode);
if (NS_FAILED(rv))
return rv;
if (accessMode != nsICache::ACCESS_WRITE)
return NS_ERROR_FAILURE;
entryDesc->SetMetaDataElement(mMetaElement, mMetaValue); // just set a bit of meta data.
entryDesc->SetExpirationTime(PRTimeToSeconds(PR_Now()) + inExpirationTimeSeconds);
entryDesc->MarkValid();
entryDesc->Close();
return NS_OK;
}
nsresult NeckoCacheHelper::ClearCache()
{
NS_ASSERTION(mCacheSession, "No cache session");
return mCacheSession->EvictEntries();
}
#pragma mark -
static nsresult MakeFaviconURIFromURI(const nsAString& inURIString, nsAString& outFaviconURI)
{
outFaviconURI.Truncate(0);
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), inURIString);
if (NS_FAILED(rv))
return rv;
// check for http/https
PRBool isHTTP = PR_FALSE, isHTTPS = PR_FALSE;
uri->SchemeIs("http", &isHTTP);
uri->SchemeIs("https", &isHTTPS);
if (!isHTTP && !isHTTPS)
return NS_OK;
PRInt32 port;
uri->GetPort(&port);
nsXPIDLCString scheme;
uri->GetScheme(scheme);
nsXPIDLCString host;
uri->GetHost(host);
nsCAutoString faviconURI = scheme;
faviconURI.Append("://");
faviconURI.Append(host);
if (port != -1) {
faviconURI.Append(':');
faviconURI.AppendInt(port);
}
faviconURI.Append("/favicon.ico");
outFaviconURI.Assign(NS_ConvertUTF8toUCS2(faviconURI));
return NS_OK;
}
@interface SiteIconProvider(Private)
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds;
- (BOOL)inMissedIconsCache:(const nsAString&)inURI;
@end
@implementation SiteIconProvider
- (id)init
{
if ((self = [super init]))
{
mMissedIconsCacheHelper = new NeckoCacheHelper("Favicon", "Missed");
nsresult rv = mMissedIconsCacheHelper->Init("MissedIconsCache");
if (NS_FAILED(rv)) {
delete mMissedIconsCacheHelper;
mMissedIconsCacheHelper = NULL;
}
}
return self;
}
- (void)dealloc
{
delete mMissedIconsCacheHelper;
[super dealloc];
}
- (void)addToMissedIconsCache:(const nsAString&)inURI withExpirationSeconds:(unsigned int)inExpSeconds
{
if (mMissedIconsCacheHelper)
{
nsresult rv = mMissedIconsCacheHelper->PutInCache(NS_ConvertUCS2toUTF8(inURI), inExpSeconds);
//NSLog(@"Putting %@ in missed icon cache", [NSString stringWith_nsAString:inURI]);
}
}
- (BOOL)inMissedIconsCache:(const nsAString&)inURI
{
PRBool inCache = PR_FALSE;
if (mMissedIconsCacheHelper)
mMissedIconsCacheHelper->ExistsInCache(NS_ConvertUCS2toUTF8(inURI), &inCache);
//NSLog(@"%@ in missed icon cache: %d", [NSString stringWith_nsAString:inURI], inCache);
return inCache;
}
- (BOOL)loadFavoriteIcon:(id)sender forURI:(NSString *)inURI withUserData:(id)userData allowNetwork:(BOOL)inAllowNetwork
{
// look for a favicon
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
if (faviconURIString.Length() == 0)
return NO;
NSString* faviconString = [NSString stringWith_nsAString:faviconURIString];
// is this uri already in the missing icons cache?
if ([self inMissedIconsCache:faviconURIString])
return NO;
RemoteDataProvider* dataProvider = [RemoteDataProvider sharedRemoteDataProvider];
return [dataProvider loadURI:faviconString forTarget:sender withListener:self withUserData:userData allowNetworking:inAllowNetwork];
}
#define SITE_ICON_EXPIRATION_SECONDS (60 * 60 * 24 * 7) // 1 week
// this is called on the main thread
- (void)doneRemoteLoad:(NSString*)inURI forTarget:(id)target withUserData:(id)userData data:(NSData*)data status:(nsresult)status
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
BOOL loadOK = NS_SUCCEEDED(status) && (data != nil);
// it's hard to tell if the favicon load succeeded or not. Even if the file
// does not exist, servers will send back a 404 page with a 0 status.
// So we just go ahead and try to make the image; it will return nil on
// failure.
NSImage* faviconImage = [[NSImage alloc] initWithData:data];
BOOL gotImageData = loadOK && (faviconImage != nil);
if (!gotImageData)
[self addToMissedIconsCache:uriString withExpirationSeconds:SITE_ICON_EXPIRATION_SECONDS];
[faviconImage setScalesWhenResized:YES];
[faviconImage setSize:NSMakeSize(16, 16)];
// we always send out the notification, so that clients know
// about failed requests
NSDictionary* notificationData = [NSDictionary dictionaryWithObjectsAndKeys:
inURI, SiteIconLoadURIKey,
faviconImage, SiteIconLoadImageKey, // may be nil
userData, SiteIconLoadUserDataKey,
nil];
[[NSNotificationCenter defaultCenter] postNotificationName: SiteIconLoadNotificationName
object:target userInfo:notificationData];
}
#pragma mark -
+ (SiteIconProvider*)sharedFavoriteIconProvider
{
static SiteIconProvider* sIconProvider = nil;
if (!sIconProvider)
{
sIconProvider = [[SiteIconProvider alloc] init];
}
return sIconProvider;
}
+ (NSString*)faviconLocationStringFromURI:(NSString*)inURI
{
nsAutoString uriString;
[inURI assignTo_nsAString:uriString];
nsAutoString faviconURIString;
MakeFaviconURIFromURI(uriString, faviconURIString);
return [NSString stringWith_nsAString:faviconURIString];
}
@end

Просмотреть файл

@ -40,7 +40,8 @@
#import <Cocoa/Cocoa.h>
@interface CHIconTabViewItem : NSTabViewItem {
@interface CHIconTabViewItem : NSTabViewItem
{
NSImage *mTabIcon;
NSDictionary* mLabelAttributes;
}

Просмотреть файл

@ -39,8 +39,9 @@
*
* ***** END LICENSE BLOCK ***** */
#import "CHIconTabViewItem.h"
#import "NSString+Utils.h"
#import "CHIconTabViewItem.h"
//
// NSParagraphStyle has a line break mode which will automatically
@ -91,7 +92,7 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
[labelParagraphStyle setLineBreakMode:NSLineBreakByTruncatingMiddle];
#endif
[labelParagraphStyle setAlignment:NSCenterTextAlignment];
[labelParagraphStyle setAlignment:NSNaturalTextAlignment];
NSFont *labelFont = [NSFont systemFontOfSize:[NSFont smallSystemFontSize]];
mLabelAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:
@ -139,9 +140,9 @@ static const int kEllipseSpaces = 4; //yes, i know it's 3 ...'s
if ([self tabIcon]) {
NSPoint drawPoint = NSMakePoint( (tabRect.origin.x), (tabRect.origin.y + 15.0) );
[[self tabIcon] compositeToPoint:drawPoint operation:NSCompositeSourceOver];
tabRect = NSMakeRect(NSMinX(tabRect)+15.0,
tabRect = NSMakeRect(NSMinX(tabRect) + 18.0,
NSMinY(tabRect),
NSWidth(tabRect)-15.0,
NSWidth(tabRect) - 18.0,
NSHeight(tabRect));
}

Просмотреть файл

@ -35,12 +35,16 @@
*
* ***** END LICENSE BLOCK ***** */
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <Carbon/Carbon.h>
@interface CHPreferenceManager : NSObject {
class nsIPref;
@interface CHPreferenceManager : NSObject
{
NSUserDefaults* mDefaults;
ICInstance mInternetConfig;
nsIPref* mPrefs;
}
+ (CHPreferenceManager *)sharedInstance;
@ -54,4 +58,9 @@
- (NSString *) getICStringPref:(ConstStr255Param) prefKey;
- (NSString *) homePage:(BOOL) checkStartupPagePref;
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess;
@end

Просмотреть файл

@ -86,8 +86,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (void) dealloc
{
::ICStop(mInternetConfig);
NS_IF_RELEASE(mPrefs);
nsresult rv;
ICStop (mInternetConfig);
nsCOMPtr<nsIPrefService> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
if (NS_SUCCEEDED(rv)) {
//NSLog(@"Saving prefs file");
@ -100,7 +102,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (BOOL) initInternetConfig
{
OSStatus error;
error = ICStart (&mInternetConfig, 'CHIM');
error = ::ICStart(&mInternetConfig, 'CHIM');
if (error != noErr) {
// XXX throw here?
NSLog(@"Error initializing IC");
@ -178,6 +180,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
return NO;
}
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
mPrefs = prefs;
NS_IF_ADDREF(mPrefs);
[self syncMozillaPrefs];
return YES;
}
@ -191,9 +197,8 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
char strbuf[1024];
int numbuf;
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs) {
// XXXw. throw?
if (!mPrefs) {
NSLog(@"Mozilla prefs not set up successfully");
return;
}
@ -201,42 +206,42 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// something that chimera can deal with.
PRInt32 acceptCookies = 0;
static const char* kCookieBehaviorPref = "network.cookie.cookieBehavior";
prefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
mPrefs->GetIntPref(kCookieBehaviorPref, &acceptCookies);
if ( acceptCookies == 1 ) { // accept foreign cookies, assume off
acceptCookies = 2;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
else if ( acceptCookies == 3 ) { // p3p, assume all cookies on
acceptCookies = 0;
prefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
mPrefs->SetIntPref(kCookieBehaviorPref, acceptCookies);
}
// get proxies from SystemConfiguration
prefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
prefs->ClearUserPref("network.proxy.http");
prefs->ClearUserPref("network.proxy.http_port");
prefs->ClearUserPref("network.proxy.ssl");
prefs->ClearUserPref("network.proxy.ssl_port");
prefs->ClearUserPref("network.proxy.ftp");
prefs->ClearUserPref("network.proxy.ftp_port");
prefs->ClearUserPref("network.proxy.gopher");
prefs->ClearUserPref("network.proxy.gopher_port");
prefs->ClearUserPref("network.proxy.socks");
prefs->ClearUserPref("network.proxy.socks_port");
prefs->ClearUserPref("network.proxy.no_proxies_on");
mPrefs->SetIntPref("network.proxy.type", 0); // 0 == no proxies
mPrefs->ClearUserPref("network.proxy.http");
mPrefs->ClearUserPref("network.proxy.http_port");
mPrefs->ClearUserPref("network.proxy.ssl");
mPrefs->ClearUserPref("network.proxy.ssl_port");
mPrefs->ClearUserPref("network.proxy.ftp");
mPrefs->ClearUserPref("network.proxy.ftp_port");
mPrefs->ClearUserPref("network.proxy.gopher");
mPrefs->ClearUserPref("network.proxy.gopher_port");
mPrefs->ClearUserPref("network.proxy.socks");
mPrefs->ClearUserPref("network.proxy.socks_port");
mPrefs->ClearUserPref("network.proxy.no_proxies_on");
if ((cfDictionary = SCDynamicStoreCopyProxies (NULL)) != NULL) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPEnable, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.http", strbuf);
mPrefs->SetCharPref("network.proxy.http", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.http_port", numbuf);
mPrefs->SetIntPref("network.proxy.http_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -245,13 +250,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ssl", strbuf);
mPrefs->SetCharPref("network.proxy.ssl", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesHTTPSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ssl_port", numbuf);
mPrefs->SetIntPref("network.proxy.ssl_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -260,13 +265,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.ftp", strbuf);
mPrefs->SetCharPref("network.proxy.ftp", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesFTPPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.ftp_port", numbuf);
mPrefs->SetIntPref("network.proxy.ftp_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -275,13 +280,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.gopher", strbuf);
mPrefs->SetCharPref("network.proxy.gopher", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesGopherPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.gopher_port", numbuf);
mPrefs->SetIntPref("network.proxy.gopher_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -290,13 +295,13 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE && numbuf == 1) {
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSProxy, (const void **)&cfString) == TRUE) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.socks", strbuf);
mPrefs->SetCharPref("network.proxy.socks", strbuf);
}
if (CFDictionaryGetValueIfPresent (cfDictionary, kSCPropNetProxiesSOCKSPort, (const void **)&cfNumber) == TRUE) {
if (CFNumberGetValue (cfNumber, kCFNumberIntType, &numbuf) == TRUE) {
prefs->SetIntPref("network.proxy.socks_port", numbuf);
mPrefs->SetIntPref("network.proxy.socks_port", numbuf);
}
prefs->SetIntPref("network.proxy.type", 1);
mPrefs->SetIntPref("network.proxy.type", 1);
}
}
}
@ -305,7 +310,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
cfString = CFStringCreateByCombiningStrings (NULL, cfArray, CFSTR(", "));
if (CFStringGetLength (cfString) > 0) {
if (CFStringGetCString (cfString, strbuf, sizeof(strbuf)-1, kCFStringEncodingASCII) == TRUE) {
prefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
mPrefs->SetCharPref("network.proxy.no_proxies_on", strbuf);
}
}
}
@ -313,24 +318,73 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
}
}
// convenience routines for mozilla prefs
- (NSString*)getMozillaPrefString: (const char*)prefName
- (NSString*)getStringPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
NSMutableString *prefValue = [[[NSMutableString alloc] init] autorelease];
NSString *prefValue = @"";
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (prefs) {
char *buf = nsnull;
nsresult rv = prefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
[prefValue setString:[NSString stringWithCString:buf]];
free(buf);
}
char *buf = nsnull;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetCharPref(prefName, &buf);
if (NS_SUCCEEDED(rv) && buf) {
// prefs are UTF-8
prefValue = [NSString stringWithUTF8String:buf];
free(buf);
if (outSuccess) *outSuccess = YES;
} else {
if (outSuccess) *outSuccess = NO;
}
return prefValue;
}
- (NSColor*)getColorPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
// colors are stored in HTML-like #FFFFFF strings
NSString* colorString = [self getStringPref:prefName withSuccess:outSuccess];
NSColor* returnColor = [NSColor blackColor];
if ([colorString hasPrefix:@"#"] && [colorString length] == 7)
{
unsigned int redInt, greenInt, blueInt;
sscanf([colorString cString], "#%02x%02x%02x", &redInt, &greenInt, &blueInt);
float redFloat = ((float)redInt / 255.0);
float greenFloat = ((float)greenInt / 255.0);
float blueFloat = ((float)blueInt / 255.0);
returnColor = [NSColor colorWithCalibratedRed:redFloat green:greenFloat blue:blueFloat alpha:1.0f];
}
return returnColor;
}
- (BOOL)getBooleanPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRBool boolPref = PR_FALSE;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
rv = mPrefs->GetBoolPref(prefName, &boolPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return boolPref ? YES : NO;
}
- (int)getIntPref: (const char*)prefName withSuccess:(BOOL*)outSuccess
{
PRInt32 intPref = 0;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefs)
mPrefs->GetIntPref(prefName, &intPref);
if (outSuccess)
*outSuccess = NS_SUCCEEDED(rv);
return intPref;
}
//- (BOOL) getICBoolPref:(ConstStr255Param) prefKey;
//{
@ -381,8 +435,7 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
- (NSString *) homePage:(BOOL)checkStartupPagePref
{
nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
if (!prefs)
if (!mPrefs)
return @"about:blank";
PRInt32 mode = 1;
@ -394,14 +447,14 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
// is true.
nsresult rv = NS_OK;
if ( checkStartupPagePref )
rv = prefs->GetIntPref("browser.startup.page", &mode);
rv = mPrefs->GetIntPref("browser.startup.page", &mode);
if (NS_FAILED(rv) || mode == 1) {
// see which home page to use
PRBool boolPref;
if (NS_SUCCEEDED(prefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
if (NS_SUCCEEDED(mPrefs->GetBoolPref("chimera.use_system_home_page", &boolPref)) && boolPref)
return [self getICStringPref:kICWWWHomePage];
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefs);
nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(mPrefs);
if (!prefBranch) return @"about:blank";
NSString* homepagePref = nil;
@ -411,10 +464,10 @@ app_getModuleInfo(nsStaticModuleInfo **info, PRUint32 *count);
homepagePref = NSLocalizedStringFromTable( @"HomePageDefault", @"WebsiteDefaults", nil);
// and let's copy this into the homepage pref if it's not bad
if (![homepagePref isEqualToString:@"HomePageDefault"])
prefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
mPrefs->SetCharPref("browser.startup.homepage", [homepagePref UTF8String]);
}
else {
homepagePref = [self getMozillaPrefString:"browser.startup.homepage"];
homepagePref = [self getStringPref:"browser.startup.homepage" withSuccess:NULL];
}
if (homepagePref && [homepagePref length] > 0 && ![homepagePref isEqualToString:@"HomePageDefault"])