WebCore:
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 May 2006 07:23:24 +0000 (07:23 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 9 May 2006 07:23:24 +0000 (07:23 +0000)
        Reviewed by Tim Hatcher.

        - refactor things so that WebKit doesn't save a WebResource for every loaded URL,
        but rather retrieves the data from the WebCore cache as needed.
        http://bugzilla.opendarwin.org/show_bug.cgi?id=8802

        * bridge/mac/WebCoreFrameBridge.h:
        * bridge/mac/WebCoreFrameBridge.mm:
        (-[WebCoreFrameBridge getData:andResponse:forURL:]):
        (-[WebCoreFrameBridge getAllResourceDatas:andResponses:]):
        * loader/Cache.cpp:
        (WebCore::Cache::updateCacheStatus):
        (WebCore::Cache::requestImage):
        (WebCore::Cache::requestStyleSheet):
        (WebCore::Cache::requestScript):
        (WebCore::Cache::requestXSLStyleSheet):
        (WebCore::Cache::requestXBLDocument):
        * loader/Cache.h:
        * loader/CachedResource.cpp: Added.
        * loader/CachedResource.h: Added.
        * loader/CachedResourceClient.h: Added.
        * loader/CachedResourceClientWalker.cpp: Added.
        * loader/CachedResourceClientWalker.h: Added.
        * loader/DocLoader.cpp:
        (WebCore::DocLoader::setAutoloadImages):
        (WebCore::DocLoader::removeCachedObject):
        * loader/DocLoader.h:
        (WebCore::DocLoader::cachedObject):
        (WebCore::DocLoader::allCachedObjects):

WebKit:

        Reviewed by Tim Hatcher.

        - refactor things so that WebKit doesn't save a WebResource for every loaded URL,
        but rather retrieves the data from the WebCore cache as needed.
        http://bugzilla.opendarwin.org/show_bug.cgi?id=8802

        * WebCoreSupport/WebFrameBridge.m:
        (-[WebFrameBridge objectLoadedFromCacheWithURL:response:data:]):
        (-[WebFrameBridge syncLoadResourceWithMethod:URL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
        * WebCoreSupport/WebSubresourceLoader.m:
        (-[WebSubresourceLoader didReceiveResponse:]):
        * WebView/WebDataSource.m:
        (-[WebDataSourcePrivate dealloc]):
        (-[WebDataSource _setupForReplaceByMIMEType:]):
        (-[WebDataSource _archivedSubresourceForURL:]):
        (-[WebDataSource initWithRequest:]):
        (-[WebDataSource subresources]):
        (-[WebDataSource subresourceForURL:]):
        (-[WebDataSource addSubresource:]):
        * WebView/WebDataSourcePrivate.h:
        * WebView/WebFrame.m:
        * WebView/WebFrameInternal.h:
        * WebView/WebHTMLView.m:
        * WebView/WebLoader.h:
        * WebView/WebLoader.m:
        (-[NSURLProtocol loadWithRequest:]):
        (-[NSURLProtocol didFinishLoading]):
        * WebView/WebUnarchivingState.h:
        * WebView/WebUnarchivingState.m:
        (-[WebUnarchivingState addResource:]):

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

24 files changed:
WebCore/ChangeLog
WebCore/bridge/mac/WebCoreFrameBridge.h
WebCore/bridge/mac/WebCoreFrameBridge.mm
WebCore/loader/Cache.cpp
WebCore/loader/Cache.h
WebCore/loader/CachedResource.cpp [new file with mode: 0644]
WebCore/loader/CachedResource.h [new file with mode: 0644]
WebCore/loader/CachedResourceClient.h [new file with mode: 0644]
WebCore/loader/CachedResourceClientWalker.cpp [new file with mode: 0644]
WebCore/loader/CachedResourceClientWalker.h [new file with mode: 0644]
WebCore/loader/DocLoader.cpp
WebCore/loader/DocLoader.h
WebKit/ChangeLog
WebKit/WebCoreSupport/WebFrameBridge.m
WebKit/WebCoreSupport/WebSubresourceLoader.m
WebKit/WebView/WebDataSource.m
WebKit/WebView/WebDataSourcePrivate.h
WebKit/WebView/WebFrame.m
WebKit/WebView/WebFrameInternal.h
WebKit/WebView/WebHTMLView.m
WebKit/WebView/WebLoader.h
WebKit/WebView/WebLoader.m
WebKit/WebView/WebUnarchivingState.h
WebKit/WebView/WebUnarchivingState.m

index d31a754ccd2df640905c8ad6183c4ca708cd4dfd..8249988089deb1327302055849de91ebd1a5049d 100644 (file)
@@ -1,3 +1,35 @@
+2006-05-08  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Tim Hatcher.
+        
+        - refactor things so that WebKit doesn't save a WebResource for every loaded URL,
+        but rather retrieves the data from the WebCore cache as needed.
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=8802
+
+        * bridge/mac/WebCoreFrameBridge.h:
+        * bridge/mac/WebCoreFrameBridge.mm:
+        (-[WebCoreFrameBridge getData:andResponse:forURL:]):
+        (-[WebCoreFrameBridge getAllResourceDatas:andResponses:]):
+        * loader/Cache.cpp:
+        (WebCore::Cache::updateCacheStatus):
+        (WebCore::Cache::requestImage):
+        (WebCore::Cache::requestStyleSheet):
+        (WebCore::Cache::requestScript):
+        (WebCore::Cache::requestXSLStyleSheet):
+        (WebCore::Cache::requestXBLDocument):
+        * loader/Cache.h:
+        * loader/CachedResource.cpp: Added.
+        * loader/CachedResource.h: Added.
+        * loader/CachedResourceClient.h: Added.
+        * loader/CachedResourceClientWalker.cpp: Added.
+        * loader/CachedResourceClientWalker.h: Added.
+        * loader/DocLoader.cpp:
+        (WebCore::DocLoader::setAutoloadImages):
+        (WebCore::DocLoader::removeCachedObject):
+        * loader/DocLoader.h:
+        (WebCore::DocLoader::cachedObject):
+        (WebCore::DocLoader::allCachedObjects):
+
 2006-05-08  Levi Weintraub  <lweintraub@apple.com>
 
         Reviewed by justin.
index 3f8844aee3bf7954e19df5478b1af26dc73b8870..ba556966e2757b0c41179f7a7a7bf0c38cf5dc66 100644 (file)
@@ -479,6 +479,9 @@ typedef enum {
 
 - (BOOL)isCharacterSmartReplaceExempt:(unichar)c isPreviousCharacter:(BOOL)isPreviousCharacter;
 
+- (BOOL)getData:(NSData **)data andResponse:(NSURLResponse **)response forURL:(NSURL *)URL;
+- (void)getAllResourceDatas:(NSArray **)datas andResponses:(NSArray **)responses;
+
 @end
 
 // The WebCoreFrameBridge protocol contains methods for use by the WebCore side of the bridge.
index 9f8d255ddf12e09f547161a3dd1f358078c5903d..cc88b2c7321b107a660e89f69e2af2e0c66c76e0 100644 (file)
@@ -29,6 +29,7 @@
 
 #import "Cache.h"
 #import "DOMInternal.h"
+#import "DocLoader.h"
 #import "DocumentFragment.h"
 #import "DocumentType.h"
 #import "FrameTree.h"
@@ -2426,6 +2427,33 @@ static NSCharacterSet *_getPostSmartSet(void)
     return [isPreviousCharacter ? _getPreSmartSet() : _getPostSmartSet() characterIsMember:c];
 }
 
+- (BOOL)getData:(NSData **)data andResponse:(NSURLResponse **)response forURL:(NSURL *)URL
+{
+    CachedObject* o = [self impl]->document()->docLoader()->cachedObject([URL absoluteString]);
+    if (!o)
+        return NO;
+
+    *data = o->allData();
+    *response = o->response();
+    return YES;
+}
+
+- (void)getAllResourceDatas:(NSArray **)datas andResponses:(NSArray **)responses
+{
+    const HashMap<String, CachedObject*>& allResources =  [self impl]->document()->docLoader()->allCachedObjects();
+    NSMutableArray *d = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
+    NSMutableArray *r = [[NSMutableArray alloc] initWithCapacity:allResources.size()];
+    
+    HashMap<String, CachedObject*>::const_iterator end = allResources.end();
+    for (HashMap<String, CachedObject*>::const_iterator it = allResources.begin(); it != end; ++it) {
+        [d addObject:it->second->allData()];
+        [r addObject:it->second->response()];
+    }
+
+    *datas = [d autorelease];
+    *responses = [r autorelease];
+}
+
 @end
 
 @implementation WebCoreFrameBridge (WebCoreBridgeInternal)
index b4dadb8fe9fd962c1dd65c27c1d5cd2e6621d52d..156de8b0aba63803a3c8a1ebde78eeb73023361b 100644 (file)
@@ -109,6 +109,17 @@ void Cache::clear()
     delete docloaders; docloaders = 0;
 }
 
+void Cache::updateCacheStatus(DocLoader* dl, const String& url, CachedObject* o)
+{
+    moveToHeadOfLRUList(o);
+    if (dl) {
+        if (cacheDisabled)
+            dl->m_docObjects.remove(url);
+        else
+            dl->m_docObjects.set(url, o);
+    }
+}
+
 CachedImage *Cache::requestImage(DocLoader* dl, const String& url, bool reload, time_t expireDate)
 {
     // this brings the _url to a standard form...
@@ -162,12 +173,7 @@ CachedImage *Cache::requestImage(DocLoader* dl, const KURL& url, bool reload, ti
         kdDebug(6060) << "Cache: using cached: " << kurl.url() << ", status " << o->status() << endl;
 #endif
 
-    moveToHeadOfLRUList(o);
-    if (dl) {
-        dl->m_docObjects.remove(o);
-        if (!cacheDisabled)
-        dl->m_docObjects.append(o);
-    }
+    updateCacheStatus(dl, o->url(), o);
     return static_cast<CachedImage *>(o);
 }
 
@@ -217,12 +223,7 @@ CachedCSSStyleSheet *Cache::requestStyleSheet(DocLoader* dl, const String& url,
         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
 #endif
 
-    moveToHeadOfLRUList(o);
-    if (dl) {
-        dl->m_docObjects.remove(o);
-        if (!cacheDisabled)
-        dl->m_docObjects.append(o);
-    }
+    updateCacheStatus(dl, url, o);
     return static_cast<CachedCSSStyleSheet *>(o);
 }
 
@@ -281,12 +282,7 @@ CachedScript *Cache::requestScript(DocLoader* dl, const String& url, bool reload
         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
 #endif
 
-    moveToHeadOfLRUList(o);
-    if (dl) {
-        dl->m_docObjects.remove(o);
-        if (!cacheDisabled)
-            dl->m_docObjects.append(o);
-    }
+    updateCacheStatus(dl, url, o);
     return static_cast<CachedScript *>(o);
 }
 
@@ -345,12 +341,7 @@ CachedXSLStyleSheet* Cache::requestXSLStyleSheet(DocLoader* dl, const String& ur
         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
 #endif
     
-    moveToHeadOfLRUList(o);
-    if (dl) {
-        dl->m_docObjects.remove(o);
-        if (!cacheDisabled)
-            dl->m_docObjects.append(o);
-    }
+    updateCacheStatus(dl, url, o);
     return static_cast<CachedXSLStyleSheet*>(o);
 }
 #endif
@@ -402,12 +393,7 @@ CachedXBLDocument* Cache::requestXBLDocument(DocLoader* dl, const String& url, b
         kdDebug(6060) << "Cache: using cached: " << kurl.url() << endl;
 #endif
     
-    moveToHeadOfLRUList(o);
-    if (dl) {
-        dl->m_docObjects.remove(o);
-        if (!cacheDisabled)
-            dl->m_docObjects.append(o);
-    }
+    updateCacheStatus(dl, url, o);
     return static_cast<CachedXBLDocument*>(o);
 }
 #endif
index b4d094a799073be134826431e96046f4dd1d4cac..c91293872cc515303a2eb5e22ab93ce2d39b9dd0 100644 (file)
@@ -177,6 +177,7 @@ namespace WebCore  {
         static Loader* m_loader;
     
         static void moveToHeadOfLRUList(CachedObject*);
+        static void updateCacheStatus(DocLoader*, const String& url, CachedObject*);
     
         static LRUList* m_LRULists;
         static int m_totalSizeOfLRULists;
diff --git a/WebCore/loader/CachedResource.cpp b/WebCore/loader/CachedResource.cpp
new file mode 100644 (file)
index 0000000..2477070
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
+    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
+    Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+
+    This class provides all functionality needed for loading images, style sheets and html
+    pages from the web. It has a memory cache for these objects.
+*/
+
+#include "config.h"
+#include "CachedObject.h"
+
+#include "Cache.h"
+#include <KURL.h>
+
+namespace WebCore {
+
+CachedObject::~CachedObject()
+{
+    if (m_deleted)
+        abort();
+    Cache::removeFromLRUList(this);
+    m_deleted = true;
+#if __APPLE__
+    setResponse(0);
+    setAllData(0);
+#endif
+}
+
+void CachedObject::finish()
+{
+    if (m_size > Cache::maxCacheableObjectSize())
+        m_status = Uncacheable;
+    else
+        m_status = Cached;
+    KURL url(m_url.deprecatedString());
+    if (m_expireDateChanged && url.protocol().startsWith("http"))
+        m_expireDateChanged = false;
+}
+
+void CachedObject::setExpireDate(time_t _expireDate, bool changeHttpCache)
+{
+    if ( _expireDate == m_expireDate)
+        return;
+
+    if (m_status == Uncacheable || m_status == Cached)
+    {
+        finish();
+    }
+    m_expireDate = _expireDate;
+    if (changeHttpCache && m_expireDate)
+       m_expireDateChanged = true;
+}
+
+bool CachedObject::isExpired() const
+{
+    if (!m_expireDate) return false;
+    time_t now = time(0);
+    return (difftime(now, m_expireDate) >= 0);
+}
+
+void CachedObject::setRequest(Request *_request)
+{
+    if ( _request && !m_request )
+        m_status = Pending;
+    m_request = _request;
+    if (canDelete() && m_free)
+        delete this;
+    else if (allowInLRUList())
+        Cache::insertInLRUList(this);
+}
+
+void CachedObject::ref(CachedObjectClient *c)
+{
+    m_clients.add(c);
+    Cache::removeFromLRUList(this);
+    increaseAccessCount();
+}
+
+void CachedObject::deref(CachedObjectClient *c)
+{
+    m_clients.remove(c);
+    if (allowInLRUList())
+        Cache::insertInLRUList(this);
+}
+
+void CachedObject::setSize(int size)
+{
+    bool sizeChanged = Cache::adjustSize(this, size - m_size);
+
+    // The object must now be moved to a different queue, since its size has been changed.
+    if (sizeChanged && allowInLRUList())
+        Cache::removeFromLRUList(this);
+
+    m_size = size;
+    
+    if (sizeChanged && allowInLRUList())
+        Cache::insertInLRUList(this);
+}
+
+}
diff --git a/WebCore/loader/CachedResource.h b/WebCore/loader/CachedResource.h
new file mode 100644 (file)
index 0000000..2fa59aa
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+    Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
+    Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+
+    This class provides all functionality needed for loading images, style sheets and html
+    pages from the web. It has a memory cache for these objects.
+*/
+
+#ifndef KHTML_CachedObject_h
+#define KHTML_CachedObject_h
+
+#include "PlatformString.h"
+#include "KWQKIOGlobal.h"
+#include <kxmlcore/HashSet.h>
+#include <time.h>
+
+#if __OBJC__
+@class NSData;
+@class NSURLResponse;
+#else
+class NSData;
+class NSURLResponse;
+#endif
+
+namespace WebCore
+{
+    class CachedObjectClient;
+    class Request;
+    
+    /**
+     *
+     * A cached object. Classes who want to use this object should derive
+     * from CachedObjectClient, to get the function calls in case the requested data has arrived.
+     *
+     * This class also does the actual communication with kio and loads the file.
+     */
+    class CachedObject
+    {
+    public:
+        enum Type {
+            ImageResource,
+            CSSStyleSheet,
+            Script
+#ifdef KHTML_XSLT
+            , XSLStyleSheet
+#endif
+#ifndef KHTML_NO_XBL
+            , XBL
+#endif
+        };
+
+        enum Status {
+            NotCached,    // this URL is not cached
+            Unknown,      // let cache decide what to do with it
+            New,          // inserting new item
+            Pending,      // only partially loaded
+            Persistent,   // never delete this
+            Cached,       // regular case
+            Uncacheable   // too big to be cached, will be destroyed as soon as possible
+        };
+
+        CachedObject(const String& URL, Type type, KIO::CacheControl cachePolicy, time_t expireDate, int size = 0)
+        {
+            m_url = URL;
+            m_type = type;
+            m_status = Pending;
+            m_size = size;
+            m_free = false;
+            m_cachePolicy = cachePolicy;
+            m_request = 0;
+#if __APPLE__
+            m_response = 0;
+            m_allData = 0;
+#endif
+            m_expireDate = expireDate;
+            m_deleted = false;
+            m_expireDateChanged = false;
+            
+            m_accessCount = 0;
+            
+            m_nextInLRUList = 0;
+            m_prevInLRUList = 0;
+        }
+        virtual ~CachedObject();
+
+        virtual void setCharset(const DeprecatedString&) {}
+        virtual void data(DeprecatedByteArray&, bool atEnd) = 0;
+        virtual void error() = 0;
+
+        const String &url() const { return m_url; }
+        Type type() const { return m_type; }
+
+        virtual void ref(CachedObjectClient*);
+        virtual void deref(CachedObjectClient*);
+
+        int count() const { return m_clients.size(); }
+
+        Status status() const { return m_status; }
+
+        int size() const { return m_size; }
+
+        bool isLoaded() const { return !m_loading; }
+
+        virtual bool isImage() const { return false; }
+
+        int accessCount() const { return m_accessCount; }
+        void increaseAccessCount() { m_accessCount++; }
+    
+        /**
+         * computes the status of an object after loading.
+         * the result depends on the objects size and the size of the cache
+         * also updates the expire date on the cache entry file
+         */
+        void finish();
+
+        /**
+         * Called by the cache if the object has been removed from the cache dict
+         * while still being referenced. This means the object should kill itself
+         * if its reference counter drops down to zero.
+         */
+        void setFree(bool b) { m_free = b; }
+
+        KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
+
+        void setRequest(Request*);
+
+#if __APPLE__
+        NSURLResponse* response() const { return m_response; }
+        void setResponse(NSURLResponse*);
+        NSData* allData() const { return m_allData; }
+        void setAllData(NSData*);
+#endif
+
+        bool canDelete() const { return m_clients.isEmpty() && !m_request; }
+
+        void setExpireDate(time_t expireDate, bool changeHttpCache);
+
+        bool isExpired() const;
+
+        virtual bool schedule() const { return false; }
+
+        // List of acceptable MIME types seperated by ",".
+        // A MIME type may contain a wildcard, e.g. "text/*".
+        DeprecatedString accept() const { return m_accept; }
+        void setAccept(const DeprecatedString& accept) { m_accept = accept; }
+
+    protected:
+        void setSize(int size);
+
+        HashSet<CachedObjectClient*> m_clients;
+
+        String m_url;
+        DeprecatedString m_accept;
+        Request *m_request;
+#if __APPLE__
+        NSURLResponse *m_response;
+        NSData *m_allData;
+#endif
+        Type m_type;
+        Status m_status;
+    private:
+        int m_size;
+        int m_accessCount;
+    
+    protected:
+        time_t m_expireDate;
+        KIO::CacheControl m_cachePolicy;
+        bool m_free : 1;
+        bool m_deleted : 1;
+        bool m_loading : 1;
+        bool m_expireDateChanged : 1;
+
+    private:
+        bool allowInLRUList() const { return canDelete() && status() != Persistent; }
+
+        CachedObject *m_nextInLRUList;
+        CachedObject *m_prevInLRUList;
+        friend class Cache;
+    };
+
+}
+
+#endif
diff --git a/WebCore/loader/CachedResourceClient.h b/WebCore/loader/CachedResourceClient.h
new file mode 100644 (file)
index 0000000..9e9ffdf
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+    Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
+    Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+
+    This class provides all functionality needed for loading images, style sheets and html
+    pages from the web. It has a memory cache for these objects.
+*/
+
+#ifndef LOADER_CACHED_OBJECT_CLIENT_H
+#define LOADER_CACHED_OBJECT_CLIENT_H
+
+#ifndef KHTML_NO_XBL
+namespace XBL {
+    class XBLDocument;
+}
+#endif
+
+namespace WebCore {
+
+    class CachedObject;
+    class CachedImage;
+    class String;
+    class Image;
+    class IntRect;
+
+    /**
+     * @internal
+     *
+     * a client who wants to load stylesheets, images or scripts from the web has to
+     * inherit from this class and overload one of the 3 functions
+     *
+     */
+    class CachedObjectClient
+    {
+    public:
+        virtual ~CachedObjectClient() { }
+
+        // Called whenever a frame of an image changes, either because we got more data from the network or
+        // because we are animating.
+        virtual void imageChanged(CachedImage*) { };
+        
+        // Called to find out if this client wants to actually display the image.  Used to tell when we
+        // can halt animation.  Content nodes that hold image refs for example would not render the image,
+        // but RenderImages would (assuming they have visibility: visible and their render tree isn't hidden
+        // e.g., in the b/f cache or in a background tab).
+        virtual bool willRenderImage(CachedImage*) { return false; }
+
+        virtual void setStyleSheet(const String& /*URL*/, const String& /*sheet*/) { }
+
+#ifndef KHTML_NO_XBL
+        virtual void setXBLDocument(const String& /*URL*/, XBL::XBLDocument*) { }
+#endif
+
+        virtual void notifyFinished(CachedObject*) { }
+    };
+
+}
+
+#endif
diff --git a/WebCore/loader/CachedResourceClientWalker.cpp b/WebCore/loader/CachedResourceClientWalker.cpp
new file mode 100644 (file)
index 0000000..25bd88c
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+    Copyright (C) 2001 Dirk Mueller (mueller@kde.org)
+    Copyright (C) 2002 Waldo Bastian (bastian@kde.org)
+    Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+
+    This class provides all functionality needed for loading images, style sheets and html
+    pages from the web. It has a memory cache for these objects.
+*/
+
+#include "config.h"
+#include "CachedObjectClientWalker.h"
+
+namespace WebCore {
+
+CachedObjectClient* CachedObjectClientWalker::next()
+{
+    while (!m_remaining.isEmpty()) {
+        CachedObjectClient* next = *m_remaining.begin();
+        m_remaining.remove(next);
+        if (m_clients.contains(next))
+            return next;
+    }
+    return 0;
+}
+
+}
diff --git a/WebCore/loader/CachedResourceClientWalker.h b/WebCore/loader/CachedResourceClientWalker.h
new file mode 100644 (file)
index 0000000..d2b36ea
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+    This file is part of the KDE libraries
+
+    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
+    Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
+    Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+
+    This class provides all functionality needed for loading images, style sheets and html
+    pages from the web. It has a memory cache for these objects.
+*/
+
+#ifndef KHTML_CachedObjectClientWalker_h
+#define KHTML_CachedObjectClientWalker_h
+
+#include <kxmlcore/HashSet.h>
+
+namespace WebCore {
+
+    class CachedObjectClient;
+
+    typedef HashSet<CachedObjectClient*> CachedObjectClientSet;
+
+    // Call this "walker" instead of iterator so people won't expect Qt or STL-style iterator interface.
+    // Just keep calling next() on this. It's safe from deletions of items.
+    class CachedObjectClientWalker {
+    public:
+        CachedObjectClientWalker(const CachedObjectClientSet& clients) : m_clients(clients), m_remaining(clients) { }
+        CachedObjectClient* next();
+    private:
+        const CachedObjectClientSet& m_clients;
+        CachedObjectClientSet m_remaining;
+    };
+
+}
+
+#endif
index 322b719ffacab6f1c96d6855af613b3d0357c927..4528ca841bfe35433408d0325c6eecd6f459032a 100644 (file)
@@ -174,7 +174,9 @@ void DocLoader::setAutoloadImages(bool enable)
     if (!m_bautoloadImages)
         return;
 
-    for (const CachedObject* co=m_docObjects.first(); co; co=m_docObjects.next())
+    HashMap<String, CachedObject*>::iterator end = m_docObjects.end();
+    for (HashMap<String, CachedObject*>::iterator it = m_docObjects.begin(); it != end; ++it) {
+        CachedObject* co = it->second;
         if (co->type() == CachedObject::ImageResource) {
             CachedImage *img = const_cast<CachedImage*>(static_cast<const CachedImage *>(co));
 
@@ -184,6 +186,7 @@ void DocLoader::setAutoloadImages(bool enable)
 
             Cache::loader()->load(this, img, true);
         }
+    }
 }
 
 void DocLoader::setCachePolicy(KIO::CacheControl cachePolicy)
@@ -193,7 +196,7 @@ void DocLoader::setCachePolicy(KIO::CacheControl cachePolicy)
 
 void DocLoader::removeCachedObject(CachedObject* o) const
 {
-    m_docObjects.removeRef(o);
+    m_docObjects.remove(o->url());
 }
 
 void DocLoader::setLoadInProgress(bool load)
index 09ebe0d2787d3e516e50424bb14b9fd262978ebe..c8ca163ecdd52dc62c13e4ba6b983073c6a52d10 100644 (file)
@@ -31,6 +31,8 @@
 #include "KWQKIOGlobal.h"
 #include "DeprecatedPtrList.h"
 #include "DeprecatedStringList.h"
+#include "kxmlcore/HashMap.h"
+#include "StringHash.h"
 
 class KURL;
 class KWQLoader;
@@ -53,27 +55,30 @@ namespace WebCore {
         DocLoader(Frame*, WebCore::Document*);
         ~DocLoader();
 
-        CachedImage *requestImage( const WebCore::String &url);
-        CachedCSSStyleSheet *requestStyleSheet( const WebCore::String &url, const DeprecatedString& charset);
-        CachedScript *requestScript( const WebCore::String &url, const DeprecatedString& charset);
+        CachedImage* requestImage(const String& url);
+        CachedCSSStyleSheet* requestStyleSheet(const String& url, const DeprecatedString& charset);
+        CachedScript* requestScript(const String& url, const DeprecatedString& charset);
 
 #ifdef KHTML_XSLT
-        CachedXSLStyleSheet* requestXSLStyleSheet(const WebCore::String& url);
+        CachedXSLStyleSheet* requestXSLStyleSheet(const String& url);
 #endif
 #ifndef KHTML_NO_XBL
-        CachedXBLDocument* requestXBLDocument(const WebCore::String &url);
+        CachedXBLDocument* requestXBLDocument(const String &url);
 #endif
 
+        CachedObject* cachedObject(const String& url) const { return m_docObjects.get(url); }
+        const HashMap<String, CachedObject*>& allCachedObjects() const { return m_docObjects; }
+
         bool autoloadImages() const { return m_bautoloadImages; }
         KIO::CacheControl cachePolicy() const { return m_cachePolicy; }
         time_t expireDate() const { return m_expireDate; }
         Frame* frame() const { return m_frame; }
         WebCore::Document* doc() const { return m_doc; }
 
-        void setExpireDate( time_t );
-        void setAutoloadImages( bool );
-        void setCachePolicy( KIO::CacheControl cachePolicy );
-        void removeCachedObject( CachedObject*) const;
+        void setExpireDate(time_t);
+        void setAutoloadImages(bool);
+        void setCachePolicy(KIO::CacheControl cachePolicy);
+        void removeCachedObject(CachedObject*) const;
 
         void setLoadInProgress(bool);
         bool loadInProgress() const { return m_loadInProgress; }
@@ -85,7 +90,7 @@ namespace WebCore {
         friend class WebCore::Document;
 
         DeprecatedStringList m_reloadedURLs;
-        mutable DeprecatedPtrList<CachedObject> m_docObjects;
+        mutable HashMap<String, CachedObject*> m_docObjects;
         time_t m_expireDate;
         KIO::CacheControl m_cachePolicy;
         bool m_bautoloadImages : 1;
index 8a97238e77778666b0e9d0b9fbf9a8f06b7d042f..19bde634c3a54176ffa7f330ed90c6b9eaa7270a 100644 (file)
@@ -1,3 +1,36 @@
+2006-05-08  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Tim Hatcher.
+        
+        - refactor things so that WebKit doesn't save a WebResource for every loaded URL,
+        but rather retrieves the data from the WebCore cache as needed.
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=8802
+
+        * WebCoreSupport/WebFrameBridge.m:
+        (-[WebFrameBridge objectLoadedFromCacheWithURL:response:data:]):
+        (-[WebFrameBridge syncLoadResourceWithMethod:URL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
+        * WebCoreSupport/WebSubresourceLoader.m:
+        (-[WebSubresourceLoader didReceiveResponse:]):
+        * WebView/WebDataSource.m:
+        (-[WebDataSourcePrivate dealloc]):
+        (-[WebDataSource _setupForReplaceByMIMEType:]):
+        (-[WebDataSource _archivedSubresourceForURL:]):
+        (-[WebDataSource initWithRequest:]):
+        (-[WebDataSource subresources]):
+        (-[WebDataSource subresourceForURL:]):
+        (-[WebDataSource addSubresource:]):
+        * WebView/WebDataSourcePrivate.h:
+        * WebView/WebFrame.m:
+        * WebView/WebFrameInternal.h:
+        * WebView/WebHTMLView.m:
+        * WebView/WebLoader.h:
+        * WebView/WebLoader.m:
+        (-[NSURLProtocol loadWithRequest:]):
+        (-[NSURLProtocol didFinishLoading]):
+        * WebView/WebUnarchivingState.h:
+        * WebView/WebUnarchivingState.m:
+        (-[WebUnarchivingState addResource:]):
+
 2006-05-04  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Reviewed by Darin.
index f631d58777e3ff45a01d45f8f429909ed63a5097..bfb9f04059d70c7e99325bfe8ee7e1fef1cc4ccb 100644 (file)
@@ -539,7 +539,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     id identifier;
     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:URL];
     [_frame _requestFromDelegateForRequest:request identifier:&identifier error:&error];    
-    [_frame _saveResourceAndSendRemainingDelegateMessagesWithRequest:request identifier:identifier response:response data:data error:error];
+    [_frame _sendRemainingDelegateMessagesWithIdentifier:identifier response:response length:[data length] error:error];
     [request release];
 }
 
@@ -605,7 +605,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
         }
     }
     
-    [_frame _saveResourceAndSendRemainingDelegateMessagesWithRequest:newRequest identifier:identifier response:response data:result error:error];
+    [_frame _sendRemainingDelegateMessagesWithIdentifier:identifier response:response length:[result length] error:error];
     [request release];
     
     return result;
index 8d405d7928ae2082e11d6517d42190b1b1bc23ea..1cd7bf51f435dbb21ed270ca017f9f8ff5053773 100644 (file)
     if (loadingMultipartContent && [[self resourceData] length]) {
         // A subresource loader does not load multipart sections progressively, deliver the previously received data to the coreLoader all at once
         [coreLoader addData:[self resourceData]];
-        // Tells the dataSource to save the just completed section, necessary for saving/dragging multipart images
-        [self saveResource];
         // Clears the data to make way for the next multipart section
         [self clearResourceData];
         
index dc9a6ad919468fe834bb030e8f3413a363cac766..33764d78788d2698e5d4c185e230f4724c22b90b 100644 (file)
@@ -92,7 +92,6 @@
     [lastCheckedRequest release];
     [responses release];
     [webFrame release];
-    [subresources release];
     [unarchivingState release];
 
     [super dealloc];
@@ -916,10 +915,14 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class,
     [_private->subresourceLoaders removeAllObjects];
     [_private->plugInStreamLoaders makeObjectsPerformSelector:@selector(cancel)];
     [_private->plugInStreamLoaders removeAllObjects];
-    [_private->subresources removeAllObjects];
     [_private->unarchivingState release];
 }
 
+- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL
+{
+    return [_private->unarchivingState archivedResourceForURL:URL];
+}
+
 @end
 
 @implementation WebDataSource
@@ -935,8 +938,6 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class,
     _private->originalRequest = [request retain];
     _private->originalRequestCopy = [request copy];
     
-    _private->subresources = [[NSMutableDictionary alloc] init];
-    
     LOG(Loading, "creating datasource for %@", [request URL]);
     _private->request = [_private->originalRequest mutableCopy];
     _private->supportsMultipartContent = WKSupportsMultipartXMixedReplace(_private->request);
@@ -1060,22 +1061,37 @@ static inline void addTypesFromClass(NSMutableDictionary *allTypes, Class class,
 
 - (NSArray *)subresources
 {
-    return [_private->subresources allValues];
+    NSArray *datas;
+    NSArray *responses;
+    [[self _bridge] getAllResourceDatas:&datas andResponses:&responses];
+    ASSERT([datas count] == [responses count]);
+
+    NSMutableArray *subresources = [[NSMutableArray alloc] initWithCapacity:[datas count]];
+    for (unsigned i = 0; i < [datas count]; ++i) {
+        NSURLResponse *response = [responses objectAtIndex:i];
+        [subresources addObject:[[[WebResource alloc] _initWithData:[datas objectAtIndex:i] URL:[response URL] response:response] autorelease]];
+    }
+
+    return [subresources autorelease];
 }
 
 - (WebResource *)subresourceForURL:(NSURL *)URL
 {
-    WebResource *resource = [_private->unarchivingState archivedResourceForURL:URL];
-    if (resource)
-        return resource;
+    NSData *data;
+    NSURLResponse *response;
+    if (![[self _bridge] getData:&data andResponse:&response forURL:URL])
+        return nil;
 
-    return [_private->subresources objectForKey:[URL _web_originalDataAsString]];
+    return [[[WebResource alloc] _initWithData:data URL:URL response:response] autorelease];
 }
 
 - (void)addSubresource:(WebResource *)subresource
 {
-    if (subresource)
-        [_private->subresources setObject:subresource forKey:[[subresource URL] _web_originalDataAsString]];
+    if (subresource) {
+        if (!_private->unarchivingState)
+            _private->unarchivingState = [[WebUnarchivingState alloc] init];
+        [_private->unarchivingState addResource:subresource];
+    }
 }
 
 @end
index 629a58359f6640b4dd6b8479cfb3f334a003c86b..4ff36aa969af7fe428657b0d70173a32a19992dc 100644 (file)
 - (void)_setupForReplaceByMIMEType:(NSString *)mimeType;
 - (BOOL)_doesProgressiveLoadWithMIMEType:(NSString *)MIMEType;
 - (void)_commitLoadWithData:(NSData *)data;
+
+- (WebResource *)_archivedSubresourceForURL:(NSURL *)URL;
+
 @end
index 728b3a1fe3642a11be1f5a36175366368e3c2840..3374f9541b43ba3e76f45cb022bb34b5444a09b9 100644 (file)
@@ -2639,23 +2639,6 @@ static CFAbsoluteTime _timeOfLastCompletedLoad;
                   formValues:nil];
 }
 
-- (void)_saveResourceAndSendRemainingDelegateMessagesWithRequest:(NSURLRequest *)request
-                                                      identifier:(id)identifier 
-                                                        response:(NSURLResponse *)response 
-                                                            data:(NSData *)data
-                                                           error:(NSError *)error
-{
-    unsigned length = [data length];
-    if (length > 0 && error == nil) {
-        ASSERT(request != nil);
-        WebResource *resource = [[WebResource alloc] _initWithData:data URL:[request URL] response:response];
-        ASSERT(resource != nil);    
-        [[self dataSource] addSubresource:resource];
-        [resource release];
-    }
-    [self _sendRemainingDelegateMessagesWithIdentifier:identifier response:response length:length error:error];
-}
-
 - (void)_unmarkAllMisspellings
 {
     for (WebFrame *frame = self; frame; frame = [frame _traverseNextFrameStayWithin:self])
index 3abb5cd10034723a0881625291ea1dd5a2b97c49..03b7bbdf8740202442b28a1756cdb2523d44fa79 100644 (file)
 - (NSURLRequest *)_requestFromDelegateForRequest:(NSURLRequest *)request identifier:(id *)identifier error:(NSError **)error;
 - (void)_sendRemainingDelegateMessagesWithIdentifier:(id)identifier response:(NSURLResponse *)response length:(unsigned)length error:(NSError *)error;
 - (void)_safeLoadURL:(NSURL *)URL;
-- (void)_saveResourceAndSendRemainingDelegateMessagesWithRequest:(NSURLRequest *)request
-                                                      identifier:(id)identifier 
-                                                        response:(NSURLResponse *)response 
-                                                            data:(NSData *)data
-                                                           error:(NSError *)error;
 - (void)_setupForReplace;
 
 - (BOOL)_hasSelection;
index 90a818099beabe3fc7255e3c7272abbc15631f19..4bb8ea4e14a9d39bbb0dfb8be17bc2f68f971a55 100644 (file)
@@ -490,27 +490,6 @@ void *_NSSoftLinkingGetFrameworkFuncPtr(NSString *inUmbrellaFrameworkName,
     return nil;
 }
 
-- (WebResource *)resourceForData:(NSData *)data preferredFilename:(NSString *)name
-{
-    // This method is called by [NSAttributedString _documentFromRange::::] 
-    // which uses the URL of the resource for the fragment that it returns.
-    NSString *extension = [name pathExtension];
-    NSString *MIMEType = nil;
-    if ([extension length] != 0)
-        MIMEType = WKGetMIMETypeForExtension(extension);
-    // Only support image resources.
-    if (MIMEType == nil || ![[[WebImageRendererFactory sharedFactory] supportedMIMETypes] containsObject:MIMEType])
-        return nil;
-    NSURL *URL = [NSURL _web_URLWithUserTypedString:[NSString stringWithFormat:@"/%@", name] relativeToURL:[NSURL _web_uniqueWebDataURL]];
-    WebResource *resource = [[[WebResource alloc] initWithData:data
-                                                           URL:URL
-                                                      MIMEType:MIMEType 
-                                              textEncodingName:nil
-                                                     frameName:nil] autorelease];
-    [[self _dataSource] addSubresource:resource];
-    return resource;
-}
-
 - (void)_pasteWithPasteboard:(NSPasteboard *)pasteboard allowPlainText:(BOOL)allowPlainText
 {
     BOOL chosePlainText;
index d3fdcd952d561c4621749db133853705ada07b4b..c39a3802a2de252df786903f227ea4ccf08c5192 100644 (file)
@@ -73,7 +73,6 @@
 }
 - (void)setSupportsMultipartContent:(BOOL)flag;
 - (void)signalFinish;
-- (void)saveResource;
 
 - (BOOL)loadWithRequest:(NSURLRequest *)request;
 
index 08513b46f1efe682b4bf417a3594a2cb557ea2af..9830760470873171d79a4c307da2a62035078da1 100644 (file)
@@ -250,7 +250,7 @@ static BOOL NSURLConnectionSupportsBufferedData;
     r = clientRequest;
     
     if ([[r URL] isEqual:originalURL] && [self _canUseResourceForRequest:r]) {
-        resource = [dataSource subresourceForURL:originalURL];
+        resource = [dataSource _archivedSubresourceForURL:originalURL];
         if (resource != nil) {
             if ([self _canUseResourceWithResponse:[resource _response]]) {
                 [resource retain];
@@ -345,25 +345,6 @@ static BOOL NSURLConnectionSupportsBufferedData;
     }
 }
 
-- (void)saveResource
-{
-    // Don't save data as a WebResource if it was loaded from a WebResource.
-    if (resource == nil) {
-        NSData *data = [self resourceData];
-        if ([data length] > 0) {
-            ASSERT(originalURL);
-            ASSERT([response MIMEType]);
-            WebResource *newResource = [[WebResource alloc] _initWithData:data URL:originalURL response:response];
-            if (newResource != nil) {
-                [dataSource addSubresource:newResource];
-                [newResource release];
-            } else {
-                ASSERT_NOT_REACHED();
-            }
-        }
-    }
-}
-
 - (NSData *)resourceData
 {
     if (resource != nil) {
@@ -572,8 +553,6 @@ static BOOL NSURLConnectionSupportsBufferedData;
     
     ASSERT(!reachedTerminalState);
 
-    [self saveResource];
-    
     if (!signalledFinish)
         [self signalFinish];
 
index 78381f049cc8f4d5e06d1fe1a060221d8dba914d..84d808b8976fbb1f9ae5764d30408e9d1421c49f 100644 (file)
@@ -38,6 +38,7 @@
 }
 
 - (void)addArchive:(WebArchive *)archive;
+- (void)addResource:(WebResource *)resource;
 - (WebResource *)archivedResourceForURL:(NSURL *)URL;
 - (WebArchive *)popSubframeArchiveWithFrameName:(NSString *)frameName;
 
index 6a3bbcf2c79310e171937f3dd691c49792727edc..6e584f7d7ec34d70c52bc55d18329cf0e58e5684 100644 (file)
     }
 }
 
+- (void)addResource:(WebResource *)subresource
+{
+    [archivedResources setObject:subresource forKey:[[subresource URL] _web_originalDataAsString]];
+}
+
 - (WebResource *)archivedResourceForURL:(NSURL *)URL
 {
     return [archivedResources objectForKey:URL];