зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
c6fde33f13
Коммит
3e9dcd40e5
|
@ -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
|
|
@ -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
|
|
@ -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"])
|
||||
|
|
Загрузка…
Ссылка в новой задаче