WebCore:
authorbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Aug 2006 07:28:51 +0000 (07:28 +0000)
committerbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 8 Aug 2006 07:28:51 +0000 (07:28 +0000)
        Reviewed by Anders and John

        Icons can now refresh when new data is sent from WebKit, both on disk and in memory

        * bridge/mac/WebCoreIconDatabaseBridge.h:
        * bridge/mac/WebCoreIconDatabaseBridge.mm:
        (WebCore::IconDatabase::loadIconFromURL):  Allows WebCore/Kit to kick off a load
        outside of any greater context
        (-[WebCoreIconDatabaseBridge isIconExpiredForIconURL:]):
        (-[WebCoreIconDatabaseBridge isIconExpiredForPageURL:]): Allows WebKit
        to get whether or not an icon has expired

        * loader/icon/IconDatabase.cpp:
        (WebCore::IconDatabase::recreateDatabase): Changed database schema slightly
        (WebCore::IconDatabase::createPrivateTables): Changed database schema slightly
        (WebCore::IconDatabase::iconForPageURL):
        (WebCore::IconDatabase::isIconExpiredForIconURL): Get if an icon has expired
        (WebCore::IconDatabase::isIconExpiredForPageURL): Get if an icon has expired
        (WebCore::IconDatabase::setIconDataForIconURL): Force a refresh of the in memory
        image when new icon data is loaded
        (WebCore::IconDatabase::setIconURLForPageURL): added a check for null iconID

        * loader/icon/IconDatabase.h: added/changed some methods
        * loader/icon/SiteIcon.cpp:
        (SiteIcon::getImage): simplified/removed debugging code
        (SiteIcon::manuallySetImageData): allow the image data to be changed when new icon
        data is loaded

WebKit:

        Reviewed by Anders and John

        * Misc/WebIconDatabase.m:
        (-[WebIconDatabase init]):
        (-[WebIconDatabase isIconExpiredForIconURL:]): Get if an icon expired
        (-[WebIconDatabase isIconExpiredForPageURL:]): Ditto
        (-[WebIconDatabase _setIconURL:forURL:]):
        (-[WebIconDatabase _sendNotificationForURL:]): Moved to WebKitPendingPublic for use outside of WebIconDatabase
        (-[WebIconDatabase loadIconFromURL:]): Allow a load outside the context of a page load
        * Misc/WebIconDatabasePrivate.h:

        * Misc/WebIconLoader.m:
        (-[WebIconLoader didFinishLoading]): fixed up the "flipping the switch" #defs a bit
        (-[WebIconLoader willSendRequest:redirectResponse:]): override to allow a load
        outside of the context of a page load

        * WebCoreSupport/WebIconDatabaseBridge.h: Added.
        * WebCoreSupport/WebIconDatabaseBridge.m: Added.
        (-[WebIconDatabaseBridge init]):
        (-[WebIconDatabaseBridge dealloc]):
        (-[WebIconDatabaseBridge loadIconFromURL:]):  Kick off a load on an icon outside
        of the context of any page load
        (-[WebIconDatabaseBridge _setIconData:forIconURL:]):  WebKit side of bridge method
        (-[WebIconDatabaseBridge _setHaveNoIconForIconURL:]):  WebKit side of bridge method
        (-[WebIconDatabaseBridge releaseCachedLoaderForIconURL:]):
        (+[WebIconDatabaseBridge sharedBridgeInstance]): Moved this from WebCore to WebKit
        so both sides of the bridge get the WebKit version
        * WebKit.xcodeproj/project.pbxproj: Added some files
        * WebView/WebDataSource.m:
        (-[WebDataSource _loadIcon]): Added check for reload/expired icon to force
        a load even if we already have it

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15815 268f45cc-cd09-0410-ab3c-d52691b4dbfc

14 files changed:
WebCore/ChangeLog
WebCore/bridge/mac/WebCoreIconDatabaseBridge.h
WebCore/bridge/mac/WebCoreIconDatabaseBridge.mm
WebCore/loader/icon/IconDatabase.cpp
WebCore/loader/icon/IconDatabase.h
WebCore/loader/icon/SiteIcon.cpp
WebKit/ChangeLog
WebKit/Misc/WebIconDatabase.m
WebKit/Misc/WebIconDatabasePrivate.h
WebKit/Misc/WebIconLoader.m
WebKit/WebCoreSupport/WebIconDatabaseBridge.h [new file with mode: 0644]
WebKit/WebCoreSupport/WebIconDatabaseBridge.m [new file with mode: 0644]
WebKit/WebKit.xcodeproj/project.pbxproj
WebKit/WebView/WebDataSource.m

index eca46c0359e81cfcead1cf894ce4d519937b3ce0..f817346002766ec3e92264824eab69cdc8227aa4 100644 (file)
@@ -1,3 +1,33 @@
+2006-08-07  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Anders and John
+
+        Icons can now refresh when new data is sent from WebKit, both on disk and in memory
+
+        * bridge/mac/WebCoreIconDatabaseBridge.h:
+        * bridge/mac/WebCoreIconDatabaseBridge.mm:
+        (WebCore::IconDatabase::loadIconFromURL):  Allows WebCore/Kit to kick off a load
+        outside of any greater context
+        (-[WebCoreIconDatabaseBridge isIconExpiredForIconURL:]):
+        (-[WebCoreIconDatabaseBridge isIconExpiredForPageURL:]): Allows WebKit
+        to get whether or not an icon has expired
+
+        * loader/icon/IconDatabase.cpp:
+        (WebCore::IconDatabase::recreateDatabase): Changed database schema slightly
+        (WebCore::IconDatabase::createPrivateTables): Changed database schema slightly
+        (WebCore::IconDatabase::iconForPageURL): 
+        (WebCore::IconDatabase::isIconExpiredForIconURL): Get if an icon has expired
+        (WebCore::IconDatabase::isIconExpiredForPageURL): Get if an icon has expired
+        (WebCore::IconDatabase::setIconDataForIconURL): Force a refresh of the in memory
+        image when new icon data is loaded
+        (WebCore::IconDatabase::setIconURLForPageURL): added a check for null iconID
+
+        * loader/icon/IconDatabase.h: added/changed some methods
+        * loader/icon/SiteIcon.cpp:
+        (SiteIcon::getImage): simplified/removed debugging code
+        (SiteIcon::manuallySetImageData): allow the image data to be changed when new icon
+        data is loaded
+
 2006-08-05  Darin Adler  <darin@apple.com>
 
         Reviewed by Eric Seidel.
index aa57ecb437746728b603ac69f44e388a9ae73f78..83539833bbf88ebc2de93e5a234486647f29dab9 100644 (file)
 namespace WebCore { 
 class IconDatabase; 
 class Image;
+class String;
 } 
 typedef WebCore::IconDatabase WebCoreIconDatabase;
 #else
 @class WebCoreIconDatabase;
 #endif
+@class WebCoreIconDatabaseBridge;
 
 @interface WebCoreIconDatabaseBridge : NSObject
 {
+    WebCoreIconDatabaseBridge *_sharedInstance;
     WebCoreIconDatabase *_iconDB;
 }
-+ (WebCoreIconDatabaseBridge *)sharedBridgeInstance;
-
 - (BOOL)openSharedDatabaseWithPath:(NSString *)path;
 - (void)closeSharedDatabase;
 - (BOOL)isOpen;
@@ -49,6 +50,9 @@ typedef WebCore::IconDatabase WebCoreIconDatabase;
 - (void)retainIconForURL:(NSString *)url;
 - (void)releaseIconForURL:(NSString *)url;
 
+- (BOOL)isIconExpiredForIconURL:(NSString *)iconURL;
+- (BOOL)isIconExpiredForPageURL:(NSString *)pageURL;
+
 - (void)setPrivateBrowsingEnabled:(BOOL)flag;
 - (BOOL)privateBrowsingEnabled;
 
@@ -57,8 +61,20 @@ typedef WebCore::IconDatabase WebCoreIconDatabase;
 - (void)_setIconURL:(NSString *)iconURL forURL:(NSString *)url;
 - (BOOL)_hasIconForIconURL:(NSString *)iconURL;
 
+@end
+
+
+// The WebCoreIconDatabaseBridge protocol contains methods for use by the WebCore side of the bridge.
 
+@protocol WebCoreIconDatabaseBridge
++ (WebCoreIconDatabaseBridge *)sharedBridgeInstance;
+- (void)loadIconFromURL:(NSString *)iconURL;
 @end
 
 
+// This interface definition allows those who hold a WebCoreIconDatabaseBridge * to call all the methods
+// in the WebCoreIconDatabaseBridge protocol without requiring the base implementation to supply the methods.
+// This idiom is appropriate because WebCoreIconDatabaseBridge is an abstract class.
 
+@interface WebCoreIconDatabaseBridge (SubclassResponsibility) <WebCoreIconDatabaseBridge>
+@end
index 32161f622fdb56d0f9d4b3a1477924af5d7a101b..d6c5b5e173135fcdc5f8ae9b086ef77e4099a133 100644 (file)
 
 using namespace WebCore;
 
-@implementation WebCoreIconDatabaseBridge
 
-+ (WebCoreIconDatabaseBridge *)sharedBridgeInstance;
+void WebCore::IconDatabase::loadIconFromURL(const String& url)
 {
-    static WebCoreIconDatabaseBridge *sharedBridgeInstance = nil;
-    if (sharedBridgeInstance) 
-        return sharedBridgeInstance;
-    return sharedBridgeInstance = [[WebCoreIconDatabaseBridge alloc] init];
+    if (url.isEmpty())
+        return;
+    [[WebCoreIconDatabaseBridge sharedBridgeInstance] loadIconFromURL:(NSString *)url];
 }
 
+@implementation WebCoreIconDatabaseBridge
+
 - (BOOL)openSharedDatabaseWithPath:(NSString *)path;
 {
     assert(path);
@@ -68,6 +68,16 @@ using namespace WebCore;
     return _iconDB != 0;
 }
 
+- (BOOL)isIconExpiredForIconURL:(NSString *)iconURL
+{
+    return _iconDB ? _iconDB->isIconExpiredForIconURL(iconURL) : NO;
+}
+
+- (BOOL)isIconExpiredForPageURL:(NSString *)pageURL
+{
+    return _iconDB ? _iconDB->isIconExpiredForPageURL(pageURL) : NO;
+}
+
 - (void)setPrivateBrowsingEnabled:(BOOL)flag;
 {
     if (_iconDB)
@@ -178,4 +188,7 @@ using namespace WebCore;
     return _iconDB->hasIconForIconURL(String(iconURL));
 }
 
+
+
+
 @end
index 5b535f405f8924671c4c4c59c312a6b43f71dae3..cf7b02e03be70a80fa38812223baae0ca0f90f37 100644 (file)
@@ -47,6 +47,12 @@ namespace WebCore {
 IconDatabase* IconDatabase::m_sharedInstance = 0;
 const int IconDatabase::currentDatabaseVersion = 3;
 
+// Icons expire once a day
+const int IconDatabase::iconExpirationTime = 60*60*24; 
+// Absent icons are rechecked once a week
+const int IconDatabase::missingIconExpirationTime = 60*60*24*7; 
+
+
 IconDatabase* IconDatabase::sharedIconDatabase()
 {
     if (!m_sharedInstance) {
@@ -150,12 +156,12 @@ void IconDatabase::recreateDatabase()
         m_db.close();
         return;
     }
-    if (!m_db.executeCommand("CREATE TABLE Icon (iconID INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL UNIQUE ON CONFLICT FAIL, expires INTEGER);")) {
+    if (!m_db.executeCommand("CREATE TABLE Icon (iconID INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL UNIQUE ON CONFLICT FAIL, stamp INTEGER);")) {
         LOG_ERROR("Could not create Icon table in icon.db (%i) - %s", m_db.lastError(), m_db.lastErrorMsg());
         m_db.close();
         return;
     }
-    if (!m_db.executeCommand("CREATE TABLE IconResource (iconID integer NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,data BLOB, touch INTEGER);")) {
+    if (!m_db.executeCommand("CREATE TABLE IconResource (iconID integer NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE, data BLOB);")) {
         LOG_ERROR("Could not create IconResource table in icon.db (%i) - %s", m_db.lastError(), m_db.lastErrorMsg());
         m_db.close();
         return;
@@ -170,7 +176,11 @@ void IconDatabase::recreateDatabase()
         m_db.close();
         return;
     }
-    
+    if (!m_db.executeCommand("CREATE TRIGGER update_icon_timestamp AFTER UPDATE ON IconResource BEGIN UPDATE Icon SET stamp = strftime('%s','now') WHERE iconID = new.iconID; END;")) {
+        LOG_ERROR("Unable to create update_icon_timestamp trigger in icon.db (%i) - %s", m_db.lastError(), m_db.lastErrorMsg());
+        m_db.close();
+        return;
+    }
 }    
 
 void IconDatabase::createPrivateTables()
@@ -178,10 +188,10 @@ void IconDatabase::createPrivateTables()
     if (!m_db.executeCommand("CREATE TEMP TABLE TempPageURL (url TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,iconID INTEGER NOT NULL ON CONFLICT FAIL);")) 
         LOG_ERROR("Could not create TempPageURL table in icon.db (%i) - %s", m_db.lastError(), m_db.lastErrorMsg());
 
-    if (!m_db.executeCommand("CREATE TEMP TABLE TempIcon (iconID INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL UNIQUE ON CONFLICT FAIL, expires INTEGER);")) 
+    if (!m_db.executeCommand("CREATE TEMP TABLE TempIcon (iconID INTEGER PRIMARY KEY AUTOINCREMENT, url TEXT NOT NULL UNIQUE ON CONFLICT FAIL, stamp INTEGER);")) 
         LOG_ERROR("Could not create TempIcon table in icon.db (%i) - %s", m_db.lastError(), m_db.lastErrorMsg());
 
-    if (!m_db.executeCommand("CREATE TEMP TABLE TempIconResource (iconID INTERGER NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,data BLOB, touch INTEGER);")) 
+    if (!m_db.executeCommand("CREATE TEMP TABLE TempIconResource (iconID INTERGER NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,data BLOB);")) 
         LOG_ERROR("Could not create TempIconResource table in icon.db (%i) - %s", m_db.lastError(), m_db.lastErrorMsg());
 
     if (!m_db.executeCommand("CREATE TEMP TRIGGER temp_create_icon_resource AFTER INSERT ON TempIcon BEGIN INSERT INTO TempIconResource (iconID, data) VALUES (new.iconID, NULL); END;")) 
@@ -231,6 +241,11 @@ Vector<unsigned char> hexStringToVector(const String& s)
         LOG(IconDatabase, "hexStringToVector() - string is invalid SQL HEX-string result - %s", s.ascii().data());
         return Vector<unsigned char>();
     }
+    if (!m_db.executeCommand("CREATE TRIGGER update_icon_timestamp AFTER UPDATE ON IconResource BEGIN UPDATE Icon SET stamp = strftime('%s','now') WHERE iconID = new.iconID; END;")) {
+        LOG_ERROR("Unable to create update_icon_timestamp trigger in icon.db (%i) - %s", m_db.lastError(), m_db.lastErrorMsg());
+        m_db.close();
+        return;        
+    }
 
     Vector<unsigned char> result;
     result.reserveCapacity(s.length() / 2);
@@ -359,12 +374,17 @@ void IconDatabase::setPrivateBrowsingEnabled(bool flag)
 
 Image* IconDatabase::iconForPageURL(const String& url, const IntSize& size, bool cache)
 {   
+    String iconURL;
+
     // We may have a SiteIcon for this specific PageURL...
     if (m_pageURLToSiteIcons.contains(url))
         return m_pageURLToSiteIcons.get(url)->getImage(size);
     
-    // Otherwise see if we even have an IconURL for this PageURL
-    String iconURL = iconURLForPageURL(url);
+    // Otherwise see if we even have an IconURL for this PageURL...
+    // The weird flow here is because we declare the iconURL variable up above, but MAY not have retrieved the string yet
+    // Trying to keep out excessive SQLite calls, which the pageURL->iconURL mapping incur
+    if (iconURL.isEmpty())
+        iconURL = iconURLForPageURL(url);
     if (iconURL.isEmpty())
         return 0;
     
@@ -383,6 +403,54 @@ Image* IconDatabase::iconForPageURL(const String& url, const IntSize& size, bool
     return icon->getImage(size);
 }
 
+// FIXME 4667425 - this check needs to see if the icon's data is empty or not and apply
+// iconExpirationTime to present icons, and missingIconExpirationTime for missing icons
+bool IconDatabase::isIconExpiredForIconURL(const String& _iconURL)
+{
+    if (_iconURL.isEmpty()) 
+        return true;
+        
+    String iconURL = _iconURL;
+    iconURL.replace('\'', "''");
+    
+    int stamp;
+    if (m_privateBrowsingEnabled) {
+        stamp = SQLStatement(m_db, "SELECT TempIcon.stamp FROM TempIcon WHERE TempIcon.url = '" + iconURL + "';").getColumnInt(0);
+        if (stamp)
+            return (time(NULL) - stamp) > iconExpirationTime;
+    }
+    stamp = SQLStatement(m_db, "SELECT Icon.stamp FROM Icon WHERE Icon.url = '" + iconURL + "';").getColumnInt(0);
+    LOG(IconDatabase, "Icon stamped at %i, now is %i", stamp, time(NULL));
+
+    if (stamp)
+        return (time(NULL) - stamp) > iconExpirationTime;
+    return false;
+}
+
+bool IconDatabase::isIconExpiredForPageURL(const String& _pageURL)
+{
+    // We don't want to encourage kicking off any loads for an empty url, so this
+    // case will always return false
+    if (_pageURL.isEmpty()) 
+        return false;
+        
+    String pageURL = _pageURL;
+    pageURL.replace('\'', "''");
+    
+    int stamp;
+    if (m_privateBrowsingEnabled) {
+        stamp = SQLStatement(m_db, "SELECT TempIcon.stamp FROM TempIcon, TempPageURL WHERE TempPageURL.url = '" + pageURL + "' AND TempIcon.iconID = TempPageURL.iconID").getColumnInt(0);
+        if (stamp)
+            return (time(NULL) - stamp) > iconExpirationTime;
+    }
+    stamp = SQLStatement(m_db, "SELECT Icon.stamp FROM Icon, PageURL WHERE PageURL.url = '" + pageURL + "' AND Icon.iconID = PageURL.iconID").getColumnInt(0);
+    
+    LOG(IconDatabase, "Icon stamped at %i, now is %i", stamp, time(NULL));
+    if (stamp)
+        return (time(NULL) - stamp) > iconExpirationTime;
+    return false;
+}
+    
 String IconDatabase::iconURLForPageURL(const String& _pageURL)
 {
     if (_pageURL.isEmpty()) 
@@ -564,6 +632,11 @@ void IconDatabase::setIconDataForIconURL(const void* data, int size, const Strin
         return;
     }
     
+    // First, if we already have a SiteIcon in memory, let's update its image data
+    if (m_iconURLToSiteIcons.contains(_iconURL))
+        m_iconURLToSiteIcons.get(_iconURL)->manuallySetImageData((unsigned char*)data, size);
+
+    // Next, we actually commit the image data to the database
     String iconURL = _iconURL;
     iconURL.replace('\'', "''");
 
@@ -691,6 +764,11 @@ void IconDatabase::setIconURLForPageURL(const String& _iconURL, const String& _p
         pageTable = "PageURL";
     }
     
+    if (!iconID) {
+        LOG_ERROR("Failed to establish an ID for iconURL %s", iconURL.ascii().data());
+        return;
+    }
+    
     performSetIconURLForPageURL(iconID, pageTable, pageURL);
 }
 
index d1339911cfe7690c9921eed3d557e729d6d8682a..d2f6a27b259f35b8d23bd56766c803c4863b5feb 100644 (file)
@@ -61,6 +61,7 @@ public:
     Image* getImage(const IntSize&);    
     String getIconURL() { return m_iconURL; }
 
+    void manuallySetImageData(unsigned char* data, int size);
 private:
     String m_iconURL;
     time_t m_expire;
@@ -97,6 +98,9 @@ public:
     bool getPrivateBrowsingEnabled() { return m_privateBrowsingEnabled; }
 
     bool hasIconForIconURL(const String&);
+
+    bool isIconExpiredForIconURL(const String&);
+    bool isIconExpiredForPageURL(const String&);
     
     // TODO - The following 3 methods were considered private in WebKit - analyze the impact of making them
     // public here in WebCore - I don't see any real badness with doing that...  after all if Chuck Norris wants to muck
@@ -106,6 +110,8 @@ public:
     void setIconURLForPageURL(const String& iconURL, const String& pageURL);
 
     static const int currentDatabaseVersion;    
+    static const int iconExpirationTime;
+    static const int missingIconExpirationTime;
 private:
     IconDatabase();
     ~IconDatabase();
@@ -162,6 +168,11 @@ private:
     Vector<unsigned char> imageDataForIconURL(const String&);
     Vector<unsigned char> imageDataForPageURL(const String&);
     
+    // FIXME: This method is currently implemented in WebCoreIconDatabaseBridge so we can be in ObjC++ and fire off a loader in Webkit
+    // Once all of the loader logic is sufficiently moved into WebCore we need to move this implementation to IconDatabase.cpp
+    // using WebCore-style loaders
+    void loadIconFromURL(const String&);
+    
     static IconDatabase* m_sharedInstance;
     static const int DefaultCachedPageCount;
     
index acf0410e81614e3454950202247182b3fe28c261..82e142d671ece6c2660b2ace18db1e8d52eccd55 100644 (file)
@@ -56,30 +56,37 @@ Image* SiteIcon::getImage(const IntSize& size)
 
         if (!imageData.size())
             return 0;
+        manuallySetImageData(imageData.data(), imageData.size());
+        
+        return m_image;
+    }
+    return 0;
+}
 
-        int checksum;
-        checksum = 0;
-#ifndef NDEBUG
-        for (unsigned int i=0; i<imageData.size(); ++i) 
-            checksum += imageData[i];
-#endif
-
-        NativeBytePtr nativeData = 0;
-        // FIXME - Any other platform will need their own method to create NativeBytePtr from the void*
+void SiteIcon::manuallySetImageData(unsigned char* data, int size)
+{
+    if (!data)
+        ASSERT(!size);
+        
+    NativeBytePtr nativeData = 0;
+    // FIXME - Any other platform will need their own method to create NativeBytePtr from the void*
 #ifdef __APPLE__
-        nativeData = CFDataCreate(NULL, imageData.data(), imageData.size());
+    nativeData = CFDataCreate(NULL, data, size);
 #endif
-        m_image = new Image();
-        
-        if (m_image->setNativeData(nativeData, true)) {
-            LOG(IconDatabase, "%s\nImage Creation SUCCESSFUL - %i bytes of data with a checksum of %i", m_iconURL.ascii().data(), imageData.size(), checksum);
-            return m_image;
-        }
-        LOG(IconDatabase, "%s\nImage Creation FAILURE - %i bytes of data with a checksum of %i", m_iconURL.ascii().data(), imageData.size(), checksum);
+
+    // It's okay to delete the raw image data here. Any existing clients using this icon will be
+    // managing an image that was created with a copy of this raw image data.
+    // FIXME: The IconDatabase interface would be more robust if it were cleaned up to never
+    // expose this raw image data.
+    if (m_image)
         delete m_image;
-        return m_image = 0;
+    m_image = new Image();
+
+    if (!m_image->setNativeData(nativeData, true)) {
+        LOG(IconDatabase, "Manual image data for iconURL '%s' FAILED", m_iconURL.ascii().data());
+        delete m_image;
+        m_image = 0;
     }
-    return 0;
 }
 
 void SiteIcon::resetExpiration(time_t newExpiration)
index afd297a86011acfeafe9326965a3bb759f1ded7a..a40e444339b362d32aaf274a7acbff63a49a559e 100644 (file)
@@ -1,3 +1,37 @@
+2006-08-07  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Anders and John
+
+        * Misc/WebIconDatabase.m:
+        (-[WebIconDatabase init]):
+        (-[WebIconDatabase isIconExpiredForIconURL:]): Get if an icon expired
+        (-[WebIconDatabase isIconExpiredForPageURL:]): Ditto
+        (-[WebIconDatabase _setIconURL:forURL:]):
+        (-[WebIconDatabase _sendNotificationForURL:]): Moved to WebKitPendingPublic for use outside of WebIconDatabase
+        (-[WebIconDatabase loadIconFromURL:]): Allow a load outside the context of a page load
+        * Misc/WebIconDatabasePrivate.h:
+
+        * Misc/WebIconLoader.m:
+        (-[WebIconLoader didFinishLoading]): fixed up the "flipping the switch" #defs a bit
+        (-[WebIconLoader willSendRequest:redirectResponse:]): override to allow a load
+        outside of the context of a page load
+
+        * WebCoreSupport/WebIconDatabaseBridge.h: Added.
+        * WebCoreSupport/WebIconDatabaseBridge.m: Added.
+        (-[WebIconDatabaseBridge init]):
+        (-[WebIconDatabaseBridge dealloc]):
+        (-[WebIconDatabaseBridge loadIconFromURL:]):  Kick off a load on an icon outside
+        of the context of any page load
+        (-[WebIconDatabaseBridge _setIconData:forIconURL:]):  WebKit side of bridge method
+        (-[WebIconDatabaseBridge _setHaveNoIconForIconURL:]):  WebKit side of bridge method
+        (-[WebIconDatabaseBridge releaseCachedLoaderForIconURL:]): 
+        (+[WebIconDatabaseBridge sharedBridgeInstance]): Moved this from WebCore to WebKit
+        so both sides of the bridge get the WebKit version
+        * WebKit.xcodeproj/project.pbxproj: Added some files
+        * WebView/WebDataSource.m:
+        (-[WebDataSource _loadIcon]): Added check for reload/expired icon to force
+        a load even if we already have it
+
 2006-08-04  Sam Weinig  <sam.weinig@gmail.com>
 
         Reviewed by Darin.
index 0c62ed742f26037ca78f14accaa2a70a9a9919cf..5be83ddd180ba72211be97c0d571c3f4cd0e670f 100644 (file)
@@ -34,7 +34,7 @@
 #import <WebKit/WebNSURLExtras.h>
 #import <WebKit/WebPreferences.h>
 
-#import <WebCore/WebCoreIconDatabaseBridge.h>
+#import <WebKit/WebIconDatabaseBridge.h>
 
 #import "WebTypesInternal.h"
 
@@ -76,7 +76,6 @@ NSSize WebIconLargeSize = {128, 128};
 - (void)_retainOriginalIconsOnDisk;
 - (void)_releaseOriginalIconsOnDisk;
 - (void)_resetCachedWebPreferences:(NSNotification *)notification;
-- (void)_sendNotificationForURL:(NSString *)URL;
 - (int)_totalRetainCountForIconURLString:(NSString *)iconURLString;
 - (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons;
 - (NSMutableDictionary *)_iconsBySplittingRepresentationsOfIcon:(NSImage *)icon;
@@ -124,7 +123,7 @@ NSSize WebIconLargeSize = {128, 128};
     _isClosing = NO;
 
 #ifdef ICONDEBUG
-    _private->databaseBridge = [WebCoreIconDatabaseBridge sharedBridgeInstance];
+    _private->databaseBridge = [WebIconDatabaseBridge sharedBridgeInstance];
     if (_private->databaseBridge) {
         NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
         NSString *databaseDirectory = [defaults objectForKey:WebIconDatabaseDirectoryDefaultsKey];
@@ -381,6 +380,16 @@ NSSize WebIconLargeSize = {128, 128};
                                                         object:self
                                                       userInfo:nil];
 }
+- (BOOL)isIconExpiredForIconURL:(NSString *)iconURL
+{
+    return [_private->databaseBridge isIconExpiredForIconURL:iconURL];
+}
+
+- (BOOL)isIconExpiredForPageURL:(NSString *)pageURL
+{
+    return [_private->databaseBridge isIconExpiredForPageURL:pageURL];
+}
+
 @end
 
 @implementation WebIconDatabase (WebPrivate)
@@ -451,6 +460,7 @@ NSSize WebIconLargeSize = {128, 128};
     
 #ifdef ICONDEBUG
     [_private->databaseBridge _setIconURL:iconURL forURL:URL];
+    [self _sendNotificationForURL:URL];
     return;
 #endif
 
@@ -501,6 +511,22 @@ NSSize WebIconLargeSize = {128, 128};
              [self _totalRetainCountForIconURLString:iconURL] > 0);
 }
 
+- (void)_sendNotificationForURL:(NSString *)URL
+{
+    ASSERT(URL);
+    
+    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:URL
+                                                         forKey:WebIconNotificationUserInfoURLKey];
+    [[NSNotificationCenter defaultCenter] postNotificationName:WebIconDatabaseDidAddIconNotification
+                                                        object:self
+                                                      userInfo:userInfo];
+}
+
+- (void)loadIconFromURL:(NSString *)iconURL
+{
+    [_private->databaseBridge loadIconFromURL:iconURL];
+}
+
 @end
 
 @implementation WebIconDatabase (WebInternal)
@@ -928,17 +954,6 @@ NSSize WebIconLargeSize = {128, 128};
     }
 }
 
-- (void)_sendNotificationForURL:(NSString *)URL
-{
-    ASSERT(URL);
-    
-    NSDictionary *userInfo = [NSDictionary dictionaryWithObject:URL
-                                                         forKey:WebIconNotificationUserInfoURLKey];
-    [[NSNotificationCenter defaultCenter] postNotificationName:WebIconDatabaseDidAddIconNotification
-                                                        object:self
-                                                      userInfo:userInfo];
-}
-
 - (NSImage *)_largestIconFromDictionary:(NSMutableDictionary *)icons
 {
     ASSERT(icons);
index 3d7f467cdbf442f595383d84219d00f5f9e8eaa6..96167bbc0346b28086d0d2a5ec693ff35f4332f6 100644 (file)
@@ -31,6 +31,7 @@
 
 @class WebFileDatabase;
 @class WebCoreIconDatabaseBridge;
+@class WebDataSource;
 
 @interface WebIconDatabasePrivate : NSObject {
 
@@ -77,6 +78,18 @@ extern NSString *WebIconDatabaseDidRemoveAllIconsNotification;
    and to send out the notification WebIconDatabaseDidRemoveAllIconsNotification.
 */
 - (void)removeAllIcons;
+
+/*!
+   @method isIconExpiredForIconURL:
+   @discussion Returns whether or not the icon at the specified URL is expired in the DB
+*/
+- (BOOL)isIconExpiredForIconURL:(NSString *)iconURL;
+
+/*!
+   @method isIconExpiredForPageURL:
+   @discussion Returns whether or not the icon associated with the specified URL is expired in the DB
+*/
+- (BOOL)isIconExpiredForPageURL:(NSString *)pageURL;
 @end
 
 @interface WebIconDatabase (WebPrivate)
@@ -91,5 +104,8 @@ extern NSString *WebIconDatabaseDidRemoveAllIconsNotification;
 - (void)_setIconURL:(NSString *)iconURL forURL:(NSString *)URL;
 
 - (BOOL)_hasIconForIconURL:(NSString *)iconURL;
+- (void)_sendNotificationForURL:(NSString *)URL;
+
+- (void)loadIconFromURL:(NSString *)iconURL;
 
 @end
index 9d4c2bb6fa27b1c77e75190929bd3d522fcf8476..fe034d09ef58d9fffbb6037ff1b977f85743b448 100644 (file)
@@ -28,9 +28,9 @@
 #import <WebKit/WebIconLoader.h>
 
 #import <JavaScriptCore/Assertions.h>
-#import <WebCore/WebCoreIconDatabaseBridge.h>
 #import <WebKit/WebFrameLoader.h>
 #import <WebKit/WebIconDatabase.h>
+#import <WebKit/WebIconDatabaseBridge.h>
 #import <WebKit/WebIconDatabasePrivate.h>
 #import <WebKit/WebKitLogging.h>
 
 
 - (void)didFinishLoading
 {
+#ifndef ICONDEBUG
     NSImage *icon;
-
+#endif
 
     NS_DURING
         NSData *data = [self resourceData];
             
-        #ifdef ICONDEBUG
+#ifdef ICONDEBUG
         if (data) {
-            [[WebCoreIconDatabaseBridge sharedBridgeInstance] _setIconData:data forIconURL:[[self URL] _web_originalDataAsString]];
+            [[WebIconDatabaseBridge sharedBridgeInstance] _setIconData:data forIconURL:[[self URL] _web_originalDataAsString]];
             LOG(IconDatabase, "NewDB - Icon data set for URL %@", [[self URL] _web_originalDataAsString]);
         }
-        #endif
-
+#else
         icon = [data length] > 0 ? [[NSImage alloc] initWithData:data] : nil;
+#endif
     NS_HANDLER
+#ifndef ICONDEBUG
         icon = nil;
+#endif
     NS_ENDHANDLER
+    
+#ifndef ICONDEBUG
     if ([[icon representations] count] > 0) {
         [[WebIconDatabase sharedIconDatabase] _setIcon:icon forIconURL:[[self URL] _web_originalDataAsString]];
     } else {
         [[WebIconDatabase sharedIconDatabase] _setHaveNoIconForIconURL:[[self URL] _web_originalDataAsString]];
     }
+#endif
+    
     [frameLoader _iconLoaderReceivedPageIcon:self];    
+    
+#ifndef ICONDEBUG
     [icon release];
+#endif
     
     [super didFinishLoading];
 }
 
+- (NSURLRequest *)willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse;
+{
+    ASSERT(!reachedTerminalState);
+    
+    // We now allow a WebIconLoader without an associated WebDataSource for kicking off a contextless icon load,
+    // so we override this special case in WebIconLoader only.  If we passed this through to the super class version,
+    // it would pass back a nil Request so the icon wouldn't actually load because it is designed to be part of a page load
+    if (!frameLoader) 
+        return newRequest;
+    return [super willSendRequest:newRequest redirectResponse:redirectResponse];
+}
+
 // We don't ever want to prompt for authentication just for a site icon, so
 // override this WebBaseResourceDelegate method to refuse the challenge
 - (void)didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
diff --git a/WebKit/WebCoreSupport/WebIconDatabaseBridge.h b/WebKit/WebCoreSupport/WebIconDatabaseBridge.h
new file mode 100644 (file)
index 0000000..db2d0a1
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import <WebCore/WebCoreIconDatabaseBridge.h>
+
+@class WebDataSource;
+
+@interface WebIconDatabaseBridge : WebCoreIconDatabaseBridge <WebCoreIconDatabaseBridge>
+{
+    NSMutableDictionary* cachedLoaders;
+}
++ (WebCoreIconDatabaseBridge *)sharedBridgeInstance;
+- (void)releaseCachedLoaderForIconURL:(NSString*)iconURL;
+- (void)loadIconFromURL:(NSString *)iconURL;
+
+@end
diff --git a/WebKit/WebCoreSupport/WebIconDatabaseBridge.m b/WebKit/WebCoreSupport/WebIconDatabaseBridge.m
new file mode 100644 (file)
index 0000000..ff52e58
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer. 
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution. 
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "WebIconDatabaseBridge.h"
+#import "WebIconDatabase.h"
+#import "WebIconDatabasePrivate.h"
+#import "WebIconLoader.h"
+
+
+@implementation WebIconDatabaseBridge
+
+- (id)init
+{
+    [super init];
+    cachedLoaders = [[NSMutableDictionary alloc] init];
+    return self;
+}
+
+- (void)dealloc
+{
+    [cachedLoaders release];
+    [super dealloc];
+}
+
+- (void)loadIconFromURL:(NSString *)iconURL
+{
+    if ([cachedLoaders valueForKey:iconURL])
+        return;
+    
+    NSURL *url = [[NSURL alloc] initWithString:iconURL];
+    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60];
+    [url release];
+    
+    WebIconLoader *iconLoader = [[WebIconLoader alloc] initWithRequest:request];
+
+    [iconLoader loadWithRequest:request];
+    [cachedLoaders setValue:iconLoader forKey:iconURL];
+    [iconLoader release];
+    [request release];
+}
+
+// FIXME rdar://4668102 - This is a likely place to add an NSNotification here to notify the app of the updated icon
+- (void)_setIconData:(NSData *)data forIconURL:(NSString *)iconURL
+{
+    [self releaseCachedLoaderForIconURL:iconURL];
+    [super _setIconData:data forIconURL:iconURL];
+}
+
+// FIXME rdar://4668102 - This is a likely place to add an NSNotification here to notify the app of the updated icon
+- (void)_setHaveNoIconForIconURL:(NSString *)iconURL
+{
+    [self releaseCachedLoaderForIconURL:iconURL];
+    [super _setHaveNoIconForIconURL:iconURL];
+}
+
+- (void)releaseCachedLoaderForIconURL:(NSString*)iconURL
+{
+    WebIconLoader *iconLoader = [cachedLoaders valueForKey:iconURL];
+    if (iconLoader) {
+        [iconLoader stopLoading];
+        [cachedLoaders removeObjectForKey:iconURL];
+    }
+}
+
++ (WebCoreIconDatabaseBridge *)sharedBridgeInstance
+{
+    static WebCoreIconDatabaseBridge* sharedBridgeInstance = nil;
+    if (!sharedBridgeInstance)
+        sharedBridgeInstance = [[WebIconDatabaseBridge alloc] init];
+    return sharedBridgeInstance;
+}
+
+@end
+
index 461c4af142c616f1b6ea5aa432638c0a0dfbdf4b..8b1b51506e28fe12740920dc3ccbde8f8134b798 100644 (file)
@@ -32,6 +32,8 @@
                22E42A4F0A5B9F620003275B /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22E42A4E0A5B9F620003275B /* OpenGL.framework */; };
                22E42A9A0A5BA4D00003275B /* AGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 22E42A990A5BA4D00003275B /* AGL.framework */; };
                22F219CC08D236730030E078 /* WebBackForwardListPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 22F219CB08D236730030E078 /* WebBackForwardListPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               51E4D3990A886B5E00ECEE2C /* WebIconDatabaseBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E4D3970A886B5E00ECEE2C /* WebIconDatabaseBridge.h */; };
+               51E4D39A0A886B5E00ECEE2C /* WebIconDatabaseBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 51E4D3980A886B5E00ECEE2C /* WebIconDatabaseBridge.m */; };
                650F74E409E488F70020118A /* WebUnarchivingState.h in Headers */ = {isa = PBXBuildFile; fileRef = 650F74E209E488F70020118A /* WebUnarchivingState.h */; };
                650F74E509E488F70020118A /* WebUnarchivingState.m in Sources */ = {isa = PBXBuildFile; fileRef = 650F74E309E488F70020118A /* WebUnarchivingState.m */; };
                65488DA1084FBCCB00831AD0 /* WebNSDictionaryExtras.h in Headers */ = {isa = PBXBuildFile; fileRef = 65488D9F084FBCCB00831AD0 /* WebNSDictionaryExtras.h */; };
                51A8B57A042834F700CA2D3A /* WebView.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebView.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                51A8B57D0428353A00CA2D3A /* WebViewPrivate.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebViewPrivate.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                51C16E4006138EB400A1657B /* npfunctions.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = npfunctions.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+               51E4D3970A886B5E00ECEE2C /* WebIconDatabaseBridge.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebIconDatabaseBridge.h; sourceTree = "<group>"; };
+               51E4D3980A886B5E00ECEE2C /* WebIconDatabaseBridge.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = WebIconDatabaseBridge.m; sourceTree = "<group>"; };
                51E94C3406C0321200A9B09E /* WebPDFView.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebPDFView.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                51E94C3506C0321200A9B09E /* WebPDFView.m */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = WebPDFView.m; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                51E94C6806C0347500A9B09E /* WebPDFRepresentation.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebPDFRepresentation.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                F5B36B400281DE87018635CB /* WebCoreSupport */ = {
                        isa = PBXGroup;
                        children = (
+                               51E4D3970A886B5E00ECEE2C /* WebIconDatabaseBridge.h */,
+                               51E4D3980A886B5E00ECEE2C /* WebIconDatabaseBridge.m */,
                                65C7F42A0979DE640022E453 /* WebPageBridge.h */,
                                65C7F42B0979DE640022E453 /* WebPageBridge.m */,
                                F5AFB45E02B94DC8018635CA /* WebFrameBridge.h */,
                                654B3C370A82C47200E1AE3D /* WebMainResourceLoader.h in Headers */,
                                654B3C390A82C47200E1AE3D /* WebNetscapePlugInStreamLoader.h in Headers */,
                                654B3C3B0A82C47200E1AE3D /* WebSubresourceLoader.h in Headers */,
+                               51E4D3990A886B5E00ECEE2C /* WebIconDatabaseBridge.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                0867D690FE84028FC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 149C283208902B0F008A9EFC /* Build configuration list for PBXProject "WebKit" */;
-                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        knownRegions = (
                                English,
                        mainGroup = 0867D691FE84028FC02AAC07 /* WebKit */;
                        productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
                        projectDirPath = "";
-                       projectRoot = "";
-                       shouldCheckCompatibility = 1;
                        targets = (
                                9398100A0824BF01008DF038 /* WebKit */,
                        );
                                654B3C380A82C47200E1AE3D /* WebMainResourceLoader.m in Sources */,
                                654B3C3A0A82C47200E1AE3D /* WebNetscapePlugInStreamLoader.m in Sources */,
                                654B3C3C0A82C47200E1AE3D /* WebSubresourceLoader.m in Sources */,
+                               51E4D39A0A886B5E00ECEE2C /* WebIconDatabaseBridge.m in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 18664734d6a3b353a3628d798bdd11301613227b..92395fdfa56894df272e65b466cc7337e69842f5 100644 (file)
 - (void)_loadIcon
 {
     // Don't load an icon if 1) this is not the main frame 2) we ended in error
-    // 3) we already did 4) they aren't saved by the DB.
-    if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || [[_private->webFrame _frameLoader] hasIconLoader] ||
-        ![[WebIconDatabase sharedIconDatabase] _isEnabled]) {
+    // 3) they aren't saved by the DB
+    if ([self webFrame] != [[self _webView] mainFrame] || _private->mainDocumentError || ![[WebIconDatabase sharedIconDatabase] _isEnabled]) {
         return;
     }
-    
+
     if (!_private->iconURL) {
         // No icon URL from the LINK tag so try the server's root.
         // This is only really a feature of http or https, so don't try this with other protocols.
                                                     relativeToURL:[self _URL]] absoluteURL] retain];
         }
     }
-    
+
     if (_private->iconURL != nil) {
+        // If we have the icon already, we'll still see if we're manually reloading or if the icon is expired
+        // If so, kick off a reload of the icon
+        // If we don't have the icon already, kick off the initial load
         if ([[WebIconDatabase sharedIconDatabase] _hasIconForIconURL:[_private->iconURL _web_originalDataAsString]]) {
+            if ([[self webFrame] _loadType] == WebFrameLoadTypeReload || [[WebIconDatabase sharedIconDatabase] isIconExpiredForIconURL:[_private->iconURL _web_originalDataAsString]])
+                [[WebIconDatabase sharedIconDatabase] loadIconFromURL:[_private->iconURL _web_originalDataAsString]];
             [self _updateIconDatabaseWithURL:_private->iconURL];
         } else {
             NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_private->iconURL];