Changeset 46344

Show
Ignore:
Timestamp:
07/24/09 02:12:30 (8 months ago)
Author:
abarth@webkit.org
Message:

2009-07-24 Andrei Popescu < andreip@google.com>

Reviewed by Anders Carlsson.

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700

Adds the WebApplicationCache class that is
used by the DumpRenderTree test application to
configure the Application Cache maximum size.

  • WebCoreSupport/WebApplicationCache.h: Added.
  • WebCoreSupport/WebApplicationCache.mm: Added.
  • WebCoreSupport/WebChromeClient.h:
  • WebCoreSupport/WebChromeClient.mm: (WebChromeClient::reachedMaxAppCacheSize): Adds empty implementation of the reachedMaxAppCacheSize callback.
  • WebKit.exp:

2009-07-24 Andrei Popescu < andreip@google.com>

Reviewed by Anders Carlsson.

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700

  • WebCoreSupport/ChromeClientQt.cpp: (WebCore::ChromeClientQt::reachedMaxAppCacheSize): Adds empty implementation of the reachedMaxAppCacheSize callback.
  • WebCoreSupport/ChromeClientQt.h:

2009-07-24 Andrei Popescu < andreip@google.com>

Reviewed by Anders Carlsson.

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700

  • WebCoreSupport/ChromeClientGtk.cpp: (WebKit::ChromeClient::reachedMaxAppCacheSize): Adds empty implementation of reachedMaxAppCacheSize.
  • WebCoreSupport/ChromeClientGtk.h:

2009-07-24 Andrei Popescu < andreip@google.com>

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700


Updated the project after adding WebApplicationCache.h/mm

  • WebKit.xcodeproj/project.pbxproj:

2009-07-24 Andrei Popescu < andreip@google.com>

Reviewed by Anders Carlsson.

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700

  • WebCoreSupport/WebChromeClient.cpp: (WebChromeClient::reachedMaxAppCacheSize): Adds empty implementation of the reachedMaxAppCacheSize callback.
  • WebCoreSupport/WebChromeClient.h:

2009-07-24 Andrei Popescu < andreip@google.com>

Reviewed by Anders Carlsson.

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700


  • WebKitSupport/ChromeClientWx.cpp: (WebCore::ChromeClientWx::reachedMaxAppCacheSize): Adds empty implementation of the reachedMaxAppCacheSize callback.
  • WebKitSupport/ChromeClientWx.h:

2009-07-24 Andrei Popescu < andreip@google.com>

Reviewed by Anders Carlsson.

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700

 https://lists.webkit.org/pipermail/webkit-dev/2009-May/007560.html

This change implements a mechanism for limiting the maximum size of
the application cache file. When this size is reached, a ChromeClient
callback is invoked asynchronously and the saving of the last (failed)
cache is retried automatically.


This change also extends the ApplicationCacheStorage API by allowing
a client to query or modify the application cache without having to
load any resources into memory.

Test: http/tests/appcache/max-size.html

  • WebCore.base.exp: Exports the symbols required by the DumpRenderTree test application.
  • loader/EmptyClients.h: Adds empty implementation of the new ChromeClient methods.
  • loader/appcache/ApplicationCache.cpp:
  • loader/appcache/ApplicationCache.h: Adds the ability to calculate the approximate size of an ApplicationCache object.
  • loader/appcache/ApplicationCacheGroup.cpp:
  • loader/appcache/ApplicationCacheGroup.h: Invokes the ChromeClient callback when the storage layer runs out of space. After the callback is invoked, we re-attempt to store the newest cache, in case the ChromeClient has freed some space.
  • loader/appcache/ApplicationCacheResource.cpp:
  • loader/appcache/ApplicationCacheResource.h: Adds the ability to calculate the approximate size of an ApplicationCacheResource object.
  • loader/appcache/ApplicationCacheStorage.cpp:
  • loader/appcache/ApplicationCacheStorage.h: Enforces a maximum size for the application cache file.
  • page/ChromeClient.h: Adds a new callback, invoked when the ApplicationCacheStorage reports that it has reached the maximum size for its database file.
  • platform/sql/SQLiteDatabase.cpp:
  • platform/sql/SQLiteDatabase.h: Adds a new method that allows querying for the amount of unused space inside the application cache database file.

2009-07-24 Andrei Popescu < andreip@google.com>

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700

Adds a unit test that ensures that the mechanism that
enforces the maximum size of the application cache is
working correctly.

  • http/tests/appcache/max-size-expected.txt: Added.
  • http/tests/appcache/max-size.html: Added.
  • http/tests/appcache/resources/maxsize.manifest: Added.

2009-07-24 Andrei Popescu < andreip@google.com>

Reviewed by Anders Carlsson.

ApplicationCache should have size limit
 https://bugs.webkit.org/show_bug.cgi?id=22700

Adds a new method on the LayoutTestController that
allows a JS unit test to configure the maximum size
of the Application Cache.

  • DumpRenderTree/LayoutTestController.cpp: (setAppCacheMaximumSizeCallback): (LayoutTestController::staticFunctions):
  • DumpRenderTree/LayoutTestController.h:
  • DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: (LayoutTestController::setAppCacheMaximumSize):
  • DumpRenderTree/mac/LayoutTestControllerMac.mm: (LayoutTestController::setAppCacheMaximumSize):
  • DumpRenderTree/win/LayoutTestControllerWin.cpp: (LayoutTestController::setAppCacheMaximumSize):
  • DumpRenderTree/wx/LayoutTestControllerWx.cpp: (LayoutTestController::setAppCacheMaximumSize):
Location:
trunk
Files:
5 added
40 modified

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r46326 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        ApplicationCache should have size limit 
     4        https://bugs.webkit.org/show_bug.cgi?id=22700 
     5 
     6        Adds a unit test that ensures that the mechanism that 
     7        enforces the maximum size of the application cache is 
     8        working correctly. 
     9 
     10        * http/tests/appcache/max-size-expected.txt: Added. 
     11        * http/tests/appcache/max-size.html: Added. 
     12        * http/tests/appcache/resources/maxsize.manifest: Added. 
     13 
    1142009-07-24  Eric Seidel  <eric@webkit.org> 
    215 
  • trunk/WebCore/ChangeLog

    r46343 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        Reviewed by Anders Carlsson. 
     4 
     5        ApplicationCache should have size limit 
     6        https://bugs.webkit.org/show_bug.cgi?id=22700 
     7 
     8        https://lists.webkit.org/pipermail/webkit-dev/2009-May/007560.html 
     9 
     10        This change implements a mechanism for limiting the maximum size of 
     11        the application cache file. When this size is reached, a ChromeClient 
     12        callback is invoked asynchronously and the saving of the last (failed) 
     13        cache is retried automatically. 
     14         
     15        This change also extends the ApplicationCacheStorage API by allowing 
     16        a client to query or modify the application cache without having to 
     17        load any resources into memory. 
     18 
     19        Test: http/tests/appcache/max-size.html 
     20 
     21        * WebCore.base.exp: 
     22        Exports the symbols required by the DumpRenderTree test application. 
     23        * loader/EmptyClients.h: 
     24        Adds empty implementation of the new ChromeClient methods. 
     25        * loader/appcache/ApplicationCache.cpp: 
     26        * loader/appcache/ApplicationCache.h: 
     27        Adds the ability to calculate the approximate size of an ApplicationCache object. 
     28        * loader/appcache/ApplicationCacheGroup.cpp: 
     29        * loader/appcache/ApplicationCacheGroup.h: 
     30        Invokes the ChromeClient callback when the storage layer runs out of space. 
     31        After the callback is invoked, we re-attempt to store the newest cache, 
     32        in case the ChromeClient has freed some space. 
     33        * loader/appcache/ApplicationCacheResource.cpp: 
     34        * loader/appcache/ApplicationCacheResource.h: 
     35        Adds the ability to calculate the approximate size of an ApplicationCacheResource object. 
     36        * loader/appcache/ApplicationCacheStorage.cpp: 
     37        * loader/appcache/ApplicationCacheStorage.h: 
     38        Enforces a maximum size for the application cache file. 
     39        * page/ChromeClient.h: 
     40        Adds a new callback, invoked when the ApplicationCacheStorage reports that it has 
     41        reached the maximum size for its database file. 
     42        * platform/sql/SQLiteDatabase.cpp: 
     43        * platform/sql/SQLiteDatabase.h: 
     44        Adds a new method that allows querying for the amount of unused space inside the 
     45        application cache database file. 
     46 
    1472009-07-24  Xan Lopez  <xlopez@igalia.com> 
    248 
  • trunk/WebCore/WebCore.base.exp

    r46298 r46344  
    446446__ZN7WebCore23ApplicationCacheStorage17setCacheDirectoryERKNS_6StringE 
    447447__ZN7WebCore23ApplicationCacheStorage5emptyEv 
     448__ZN7WebCore23ApplicationCacheStorage14setMaximumSizeEx 
     449__ZN7WebCore23ApplicationCacheStorage18vacuumDatabaseFileEv 
    448450__ZN7WebCore23ReplaceSelectionCommandC1EPNS_8DocumentEN3WTF10PassRefPtrINS_16DocumentFragmentEEEbbbbbNS_10EditActionE 
    449451__ZN7WebCore23createFragmentFromNodesEPNS_8DocumentERKN3WTF6VectorIPNS_4NodeELm0EEE 
  • trunk/WebCore/loader/EmptyClients.h

    r45991 r46344  
    134134#endif 
    135135 
     136#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     137    virtual void reachedMaxAppCacheSize(int64_t) { } 
     138#endif 
     139 
    136140    virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) { } 
    137141 
  • trunk/WebCore/loader/appcache/ApplicationCache.cpp

    r45848 r46344  
    4040    : m_group(0) 
    4141    , m_manifest(0) 
     42    , m_estimatedSizeInStorage(0) 
    4243    , m_storageID(0) 
    4344{ 
     
    8788        cacheStorage().store(resource.get(), this); 
    8889    } 
    89      
     90 
     91    m_estimatedSizeInStorage += resource->estimatedSizeInStorage(); 
     92 
    9093    m_resources.set(url, resource); 
    9194} 
     
    101104 
    102105    m_resources.remove(it); 
    103      
     106 
     107    m_estimatedSizeInStorage -= it->second->estimatedSizeInStorage(); 
     108 
    104109    return type; 
    105110}     
  • trunk/WebCore/loader/appcache/ApplicationCache.h

    r44943 r46344  
    8888    static bool requestIsHTTPOrHTTPSGet(const ResourceRequest&); 
    8989 
     90    int64_t estimatedSizeInStorage() const { return m_estimatedSizeInStorage; } 
     91 
    9092private: 
    9193    ApplicationCache(); 
     
    98100    FallbackURLVector m_fallbackURLs; 
    99101 
     102    // The total size of the resources belonging to this Application Cache instance. 
     103    // This is an estimation of the size this Application Cache occupies in the 
     104    // database file. 
     105    int64_t m_estimatedSizeInStorage; 
     106 
    100107    unsigned m_storageID; 
    101108}; 
  • trunk/WebCore/loader/appcache/ApplicationCacheGroup.cpp

    r46058 r46344  
    3232#include "ApplicationCacheResource.h" 
    3333#include "ApplicationCacheStorage.h" 
     34#include "ChromeClient.h" 
    3435#include "DocumentLoader.h" 
    3536#include "DOMApplicationCache.h" 
     
    5455    , m_completionType(None) 
    5556    , m_isCopy(isCopy) 
     57    , m_calledReachedMaxAppCacheSize(false) 
    5658{ 
    5759} 
     
    674676} 
    675677 
     678void ApplicationCacheGroup::didReachMaxAppCacheSize() 
     679{ 
     680    ASSERT(m_frame); 
     681    ASSERT(m_cacheBeingUpdated); 
     682    m_frame->page()->chrome()->client()->reachedMaxAppCacheSize(cacheStorage().spaceNeeded(m_cacheBeingUpdated->estimatedSizeInStorage())); 
     683    m_calledReachedMaxAppCacheSize = true; 
     684    checkIfLoadIsComplete(); 
     685} 
     686 
    676687void ApplicationCacheGroup::cacheUpdateFailed() 
    677688{ 
     
    752763 
    753764        ASSERT(m_cacheBeingUpdated); 
    754         m_cacheBeingUpdated->setManifestResource(m_manifestResource.release()); 
     765        if (m_manifestResource) 
     766            m_cacheBeingUpdated->setManifestResource(m_manifestResource.release()); 
     767        else { 
     768            // We can get here as a result of retrying the Complete step, following 
     769            // a failure of the cache storage to save the newest cache due to hitting 
     770            // the maximum size. In such a case, m_manifestResource may be 0, as 
     771            // the manifest was already set on the newest cache object. 
     772            ASSERT(cacheStorage().isMaximumSizeReached() && m_calledReachedMaxAppCacheSize); 
     773        } 
    755774 
    756775        RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? 0 : m_newestCache; 
     
    764783            postListenerTask(isUpgradeAttempt ? &DOMApplicationCache::callUpdateReadyListener : &DOMApplicationCache::callCachedListener, m_associatedDocumentLoaders); 
    765784        } else { 
    766             // Run the "cache failure steps" 
    767             // Fire the error events to all pending master entries, as well any other cache hosts 
    768             // currently associated with a cache in this group. 
    769             postListenerTask(&DOMApplicationCache::callErrorListener, m_associatedDocumentLoaders); 
    770             // Disassociate the pending master entries from the failed new cache. Note that 
    771             // all other loaders in the m_associatedDocumentLoaders are still associated with 
    772             // some other cache in this group. They are not associated with the failed new cache. 
    773  
    774             // Need to copy loaders, because the cache group may be destroyed at the end of iteration. 
    775             Vector<DocumentLoader*> loaders; 
    776             copyToVector(m_pendingMasterResourceLoaders, loaders); 
    777             size_t count = loaders.size(); 
    778             for (size_t i = 0; i != count; ++i) 
    779                 disassociateDocumentLoader(loaders[i]); // This can delete this group. 
    780  
    781             // Reinstate the oldNewestCache, if there was one. 
    782             if (oldNewestCache) { 
    783                 // This will discard the failed new cache. 
    784                 setNewestCache(oldNewestCache.release()); 
     785            if (cacheStorage().isMaximumSizeReached() && !m_calledReachedMaxAppCacheSize) { 
     786                // We ran out of space. All the changes in the cache storage have 
     787                // been rolled back. We roll back to the previous state in here, 
     788                // as well, call the chrome client asynchronously and retry to 
     789                // save the new cache. 
     790 
     791                // Save a reference to the new cache. 
     792                m_cacheBeingUpdated = m_newestCache.release(); 
     793                if (oldNewestCache) { 
     794                    // Reinstate the oldNewestCache. 
     795                    setNewestCache(oldNewestCache.release()); 
     796                } 
     797                scheduleReachedMaxAppCacheSizeCallback(); 
     798                return; 
    785799            } else { 
    786                 // We must have been deleted by the last call to disassociateDocumentLoader(). 
    787                 return; 
     800                // Run the "cache failure steps" 
     801                // Fire the error events to all pending master entries, as well any other cache hosts 
     802                // currently associated with a cache in this group. 
     803                postListenerTask(&DOMApplicationCache::callErrorListener, m_associatedDocumentLoaders); 
     804                // Disassociate the pending master entries from the failed new cache. Note that 
     805                // all other loaders in the m_associatedDocumentLoaders are still associated with 
     806                // some other cache in this group. They are not associated with the failed new cache. 
     807 
     808                // Need to copy loaders, because the cache group may be destroyed at the end of iteration. 
     809                Vector<DocumentLoader*> loaders; 
     810                copyToVector(m_pendingMasterResourceLoaders, loaders); 
     811                size_t count = loaders.size(); 
     812                for (size_t i = 0; i != count; ++i) 
     813                    disassociateDocumentLoader(loaders[i]); // This can delete this group. 
     814 
     815                // Reinstate the oldNewestCache, if there was one. 
     816                if (oldNewestCache) { 
     817                    // This will discard the failed new cache. 
     818                    setNewestCache(oldNewestCache.release()); 
     819                } else { 
     820                    // We must have been deleted by the last call to disassociateDocumentLoader(). 
     821                    return; 
     822                } 
    788823            } 
    789824        } 
     
    797832    m_updateStatus = Idle; 
    798833    m_frame = 0; 
     834    m_calledReachedMaxAppCacheSize = false; 
    799835} 
    800836 
     
    880916    m_associatedDocumentLoaders.add(loader); 
    881917} 
    882   
     918 
     919class ChromeClientCallbackTimer: public TimerBase { 
     920public: 
     921    ChromeClientCallbackTimer(ApplicationCacheGroup* cacheGroup) 
     922        : m_cacheGroup(cacheGroup) 
     923    { 
     924    } 
     925 
     926private: 
     927    virtual void fired() 
     928    { 
     929        m_cacheGroup->didReachMaxAppCacheSize(); 
     930        delete this; 
     931    } 
     932    // Note that there is no need to use a RefPtr here. The ApplicationCacheGroup instance is guaranteed 
     933    // to be alive when the timer fires since invoking the ChromeClient callback is part of its normal 
     934    // update machinery and nothing can yet cause it to get deleted. 
     935    ApplicationCacheGroup* m_cacheGroup; 
     936}; 
     937 
     938void ApplicationCacheGroup::scheduleReachedMaxAppCacheSizeCallback() 
     939{ 
     940    ASSERT(isMainThread()); 
     941    ChromeClientCallbackTimer* timer = new ChromeClientCallbackTimer(this); 
     942    timer->startOneShot(0); 
     943    // The timer will delete itself once it fires. 
     944} 
     945 
    883946class CallCacheListenerTask : public ScriptExecutionContext::Task { 
    884947    typedef void (DOMApplicationCache::*ListenerFunction)(); 
     
    933996        (*it)->clearStorageID(); 
    934997} 
    935      
     998 
    936999 
    9371000} 
  • trunk/WebCore/loader/appcache/ApplicationCacheGroup.h

    r45891 r46344  
    9696    static void postListenerTask(ListenerFunction, const Vector<RefPtr<DocumentLoader> >& loaders); 
    9797    static void postListenerTask(ListenerFunction, DocumentLoader*); 
     98    void scheduleReachedMaxAppCacheSizeCallback(); 
    9899 
    99100    PassRefPtr<ResourceHandle> createResourceHandle(const KURL&, ApplicationCacheResource* newestCachedResource); 
     
    107108    void didReceiveManifestData(const char*, int); 
    108109    void didFinishLoadingManifest(); 
     110    void didReachMaxAppCacheSize(); 
    109111     
    110112    void startLoadingEntry(); 
     
    164166    // Whether this cache group is a copy that's only used for transferring the cache to another file. 
    165167    bool m_isCopy; 
     168 
     169    // This flag is set immediately after the ChromeClient::reachedMaxAppCacheSize() callback is invoked as a result of the storage layer failing to save a cache 
     170    // due to reaching the maximum size of the application cache database file. This flag is used by ApplicationCacheGroup::checkIfLoadIsComplete() to decide 
     171    // the course of action in case of this failure (i.e. call the ChromeClient callback or run the failure steps). 
     172    bool m_calledReachedMaxAppCacheSize; 
    166173     
    167174    RefPtr<ResourceHandle> m_currentHandle; 
     
    170177    RefPtr<ApplicationCacheResource> m_manifestResource; 
    171178    RefPtr<ResourceHandle> m_manifestHandle; 
     179 
     180    friend class ChromeClientCallbackTimer; 
    172181}; 
    173182 
  • trunk/WebCore/loader/appcache/ApplicationCacheResource.cpp

    r44943 r46344  
    3636    , m_type(type) 
    3737    , m_storageID(0) 
     38    , m_estimatedSizeInStorage(0) 
    3839{ 
    3940} 
     
    4344    // Caller should take care of storing the new type in database. 
    4445    m_type |= type;  
     46} 
     47 
     48int64_t ApplicationCacheResource::estimatedSizeInStorage() 
     49{ 
     50    if (m_estimatedSizeInStorage) 
     51      return m_estimatedSizeInStorage; 
     52 
     53    if (data()) 
     54        m_estimatedSizeInStorage = data()->size(); 
     55 
     56    HTTPHeaderMap::const_iterator end = response().httpHeaderFields().end(); 
     57    for (HTTPHeaderMap::const_iterator it = response().httpHeaderFields().begin(); it != end; ++it) 
     58        m_estimatedSizeInStorage += (it->first.length() + it->second.length() + 2) * sizeof(UChar); 
     59 
     60    m_estimatedSizeInStorage += url().string().length() * sizeof(UChar); 
     61    m_estimatedSizeInStorage += sizeof(int); // response().m_httpStatusCode 
     62    m_estimatedSizeInStorage += response().url().string().length() * sizeof(UChar); 
     63    m_estimatedSizeInStorage += sizeof(unsigned); // dataId 
     64    m_estimatedSizeInStorage += response().mimeType().length() * sizeof(UChar); 
     65    m_estimatedSizeInStorage += response().textEncodingName().length() * sizeof(UChar); 
     66 
     67    return m_estimatedSizeInStorage; 
    4568} 
    4669 
  • trunk/WebCore/loader/appcache/ApplicationCacheResource.h

    r45848 r46344  
    5555    unsigned storageID() const { return m_storageID; } 
    5656    void clearStorageID() { m_storageID = 0; } 
     57    int64_t estimatedSizeInStorage(); 
    5758 
    5859#ifndef NDEBUG 
     
    6566    unsigned m_type; 
    6667    unsigned m_storageID; 
     68    int64_t m_estimatedSizeInStorage; 
    6769}; 
    6870     
  • trunk/WebCore/loader/appcache/ApplicationCacheStorage.cpp

    r45848 r46344  
    4444namespace WebCore { 
    4545 
    46 class ResourceStorageIDJournal { 
     46template <class T> 
     47class StorageIDJournal { 
    4748public:   
    48     ~ResourceStorageIDJournal() 
     49    ~StorageIDJournal() 
    4950    { 
    5051        size_t size = m_records.size(); 
     
    5354    } 
    5455 
    55     void add(ApplicationCacheResource* resource, unsigned storageID) 
     56    void add(T* resource, unsigned storageID) 
    5657    { 
    5758        m_records.append(Record(resource, storageID)); 
     
    6768    public: 
    6869        Record() : m_resource(0), m_storageID(0) { } 
    69         Record(ApplicationCacheResource* resource, unsigned storageID) : m_resource(resource), m_storageID(storageID) { } 
     70        Record(T* resource, unsigned storageID) : m_resource(resource), m_storageID(storageID) { } 
    7071 
    7172        void restore() 
     
    7576 
    7677    private: 
    77         ApplicationCacheResource* m_resource; 
     78        T* m_resource; 
    7879        unsigned m_storageID; 
    7980    }; 
     
    227228        unsigned newestCacheID = static_cast<unsigned>(statement.getColumnInt64(2)); 
    228229        RefPtr<ApplicationCache> cache = loadCache(newestCacheID); 
     230        if (!cache) 
     231            continue; 
    229232 
    230233        ApplicationCacheResource* resource = cache->resourceForURL(url); 
     
    359362} 
    360363 
     364void ApplicationCacheStorage::setMaximumSize(int64_t size) 
     365{ 
     366    m_maximumSize = size; 
     367} 
     368 
     369int64_t ApplicationCacheStorage::maximumSize() const 
     370{ 
     371    return m_maximumSize; 
     372} 
     373 
     374bool ApplicationCacheStorage::isMaximumSizeReached() const 
     375{ 
     376    return m_isMaximumSizeReached; 
     377} 
     378 
     379int64_t ApplicationCacheStorage::spaceNeeded(int64_t cacheToSave) 
     380{ 
     381    int64_t spaceNeeded = 0; 
     382    int64_t currentSize = 0; 
     383    if (!getFileSize(m_cacheFile, currentSize)) 
     384        return 0; 
     385 
     386    // Determine the amount of free space we have available. 
     387    int64_t totalAvailableSize = 0; 
     388    if (m_maximumSize < currentSize) { 
     389        // The max size is smaller than the actual size of the app cache file. 
     390        // This can happen if the client previously imposed a larger max size 
     391        // value and the app cache file has already grown beyond the current 
     392        // max size value. 
     393        // The amount of free space is just the amount of free space inside 
     394        // the database file. Note that this is always 0 if SQLite is compiled 
     395        // with AUTO_VACUUM = 1. 
     396        totalAvailableSize = m_database.freeSpaceSize(); 
     397    } else { 
     398        // The max size is the same or larger than the current size. 
     399        // The amount of free space available is the amount of free space 
     400        // inside the database file plus the amount we can grow until we hit 
     401        // the max size. 
     402        totalAvailableSize = (m_maximumSize - currentSize) + m_database.freeSpaceSize(); 
     403    } 
     404 
     405    // The space needed to be freed in order to accomodate the failed cache is 
     406    // the size of the failed cache minus any already available free space. 
     407    spaceNeeded = cacheToSave - totalAvailableSize; 
     408    // The space needed value must be positive (or else the total already 
     409    // available free space would be larger than the size of the failed cache and 
     410    // saving of the cache should have never failed). 
     411    ASSERT(spaceNeeded); 
     412    return spaceNeeded; 
     413} 
    361414 
    362415bool ApplicationCacheStorage::executeSQLCommand(const String& sql) 
     
    372425} 
    373426 
    374 static const int schemaVersion = 3; 
     427static const int schemaVersion = 4; 
    375428     
    376429void ApplicationCacheStorage::verifySchemaVersion() 
     
    406459    if (m_cacheDirectory.isNull()) 
    407460        return; 
    408      
    409     String applicationCachePath = pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db"); 
    410     if (!createIfDoesNotExist && !fileExists(applicationCachePath)) 
     461 
     462    m_cacheFile = pathByAppendingComponent(m_cacheDirectory, "ApplicationCache.db"); 
     463    if (!createIfDoesNotExist && !fileExists(m_cacheFile)) 
    411464        return; 
    412465 
    413466    makeAllDirectories(m_cacheDirectory); 
    414     m_database.open(applicationCachePath); 
     467    m_database.open(m_cacheFile); 
    415468     
    416469    if (!m_database.isOpen()) 
     
    422475    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheGroups (id INTEGER PRIMARY KEY AUTOINCREMENT, " 
    423476                      "manifestHostHash INTEGER NOT NULL ON CONFLICT FAIL, manifestURL TEXT UNIQUE ON CONFLICT FAIL, newestCache INTEGER)"); 
    424     executeSQLCommand("CREATE TABLE IF NOT EXISTS Caches (id INTEGER PRIMARY KEY AUTOINCREMENT, cacheGroup INTEGER)"); 
     477    executeSQLCommand("CREATE TABLE IF NOT EXISTS Caches (id INTEGER PRIMARY KEY AUTOINCREMENT, cacheGroup INTEGER, size INTEGER)"); 
    425478    executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheWhitelistURLs (url TEXT NOT NULL ON CONFLICT FAIL, cache INTEGER NOT NULL ON CONFLICT FAIL)"); 
    426479    executeSQLCommand("CREATE TABLE IF NOT EXISTS FallbackURLs (namespace TEXT NOT NULL ON CONFLICT FAIL, fallbackURL TEXT NOT NULL ON CONFLICT FAIL, " 
     
    462515}     
    463516 
    464 bool ApplicationCacheStorage::store(ApplicationCacheGroup* group) 
     517bool ApplicationCacheStorage::store(ApplicationCacheGroup* group, GroupStorageIDJournal* journal) 
    465518{ 
    466519    ASSERT(group->storageID() == 0); 
     520    ASSERT(journal); 
    467521 
    468522    SQLiteStatement statement(m_database, "INSERT INTO CacheGroups (manifestHostHash, manifestURL) VALUES (?, ?)"); 
     
    477531 
    478532    group->setStorageID(static_cast<unsigned>(m_database.lastInsertRowID())); 
     533    journal->add(group, 0); 
    479534    return true; 
    480535}     
     
    486541    ASSERT(storageIDJournal); 
    487542     
    488     SQLiteStatement statement(m_database, "INSERT INTO Caches (cacheGroup) VALUES (?)"); 
     543    SQLiteStatement statement(m_database, "INSERT INTO Caches (cacheGroup, size) VALUES (?, ?)"); 
    489544    if (statement.prepare() != SQLResultOk) 
    490545        return false; 
    491546 
    492547    statement.bindInt64(1, cache->group()->storageID()); 
     548    statement.bindInt64(2, cache->estimatedSizeInStorage()); 
    493549 
    494550    if (!executeStatement(statement)) 
     
    587643        return false; 
    588644     
     645    // The same ApplicationCacheResource are used in ApplicationCacheResource::size() 
     646    // to calculate the approximate size of an ApplicationCacheResource object. If 
     647    // you change the code below, please also change ApplicationCacheResource::size(). 
    589648    resourceStatement.bindText(1, resource->url()); 
    590649    resourceStatement.bindInt64(2, resource->response().httpStatusCode()); 
     
    632691} 
    633692 
    634 void ApplicationCacheStorage::store(ApplicationCacheResource* resource, ApplicationCache* cache) 
     693bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, ApplicationCache* cache) 
    635694{ 
    636695    ASSERT(cache->storageID()); 
     
    638697    openDatabase(true); 
    639698  
     699    m_isMaximumSizeReached = false; 
     700    m_database.setMaximumSize(m_maximumSize); 
     701 
    640702    SQLiteTransaction storeResourceTransaction(m_database); 
    641703    storeResourceTransaction.begin(); 
    642704     
    643     if (!store(resource, cache->storageID())) 
    644         return; 
     705    if (!store(resource, cache->storageID())) { 
     706        checkForMaxSizeReached(); 
     707        return false; 
     708    } 
     709 
     710    // A resource was added to the cache. Update the total data size for the cache. 
     711    SQLiteStatement sizeUpdateStatement(m_database, "UPDATE Caches SET size=size+? WHERE id=?"); 
     712    if (sizeUpdateStatement.prepare() != SQLResultOk) 
     713        return false; 
     714 
     715    sizeUpdateStatement.bindInt64(1, resource->estimatedSizeInStorage()); 
     716    sizeUpdateStatement.bindInt64(2, cache->storageID()); 
     717 
     718    if (!executeStatement(sizeUpdateStatement)) 
     719        return false; 
    645720     
    646721    storeResourceTransaction.commit(); 
     722    return true; 
    647723} 
    648724 
     
    650726{ 
    651727    openDatabase(true); 
    652      
     728 
     729    m_isMaximumSizeReached = false; 
     730    m_database.setMaximumSize(m_maximumSize); 
     731 
    653732    SQLiteTransaction storeCacheTransaction(m_database); 
    654733     
    655734    storeCacheTransaction.begin(); 
    656      
     735 
     736    GroupStorageIDJournal groupStorageIDJournal; 
    657737    if (!group->storageID()) { 
    658738        // Store the group 
    659         if (!store(group)) 
     739        if (!store(group, &groupStorageIDJournal)) { 
     740            checkForMaxSizeReached(); 
    660741            return false; 
     742        } 
    661743    } 
    662744     
     
    668750    // object will roll them back automatically in case a database operation 
    669751    // fails and this method returns early. 
    670     ResourceStorageIDJournal storageIDJournal; 
     752    ResourceStorageIDJournal resourceStorageIDJournal; 
    671753 
    672754    // Store the newest cache 
    673     if (!store(group->newestCache(), &storageIDJournal)) 
    674         return false; 
     755    if (!store(group->newestCache(), &resourceStorageIDJournal)) { 
     756        checkForMaxSizeReached(); 
     757        return false; 
     758    } 
    675759     
    676760    // Update the newest cache in the group. 
     
    686770        return false; 
    687771     
    688     storageIDJournal.commit(); 
     772    groupStorageIDJournal.commit(); 
     773    resourceStorageIDJournal.commit(); 
    689774    storeCacheTransaction.commit(); 
    690775    return true; 
     
    882967    return copyStorage.storeNewestCache(groupCopy.get()); 
    883968} 
    884      
     969 
     970bool ApplicationCacheStorage::manifestURLs(Vector<KURL>* urls) 
     971{ 
     972    ASSERT(urls); 
     973    openDatabase(false); 
     974    if (!m_database.isOpen()) 
     975        return false; 
     976 
     977    SQLiteStatement selectURLs(m_database, "SELECT manifestURL FROM CacheGroups"); 
     978 
     979    if (selectURLs.prepare() != SQLResultOk) 
     980        return false; 
     981 
     982    while (selectURLs.step() == SQLResultRow) 
     983        urls->append(selectURLs.getColumnText(0)); 
     984 
     985    return true; 
     986} 
     987 
     988bool ApplicationCacheStorage::cacheGroupSize(const String& manifestURL, int64_t* size) 
     989{ 
     990    ASSERT(size); 
     991    openDatabase(false); 
     992    if (!m_database.isOpen()) 
     993        return false; 
     994 
     995    SQLiteStatement statement(m_database, "SELECT sum(Caches.size) FROM Caches INNER JOIN CacheGroups ON Caches.cacheGroup=CacheGroups.id WHERE CacheGroups.manifestURL=?"); 
     996    if (statement.prepare() != SQLResultOk) 
     997        return false; 
     998 
     999    statement.bindText(1, manifestURL); 
     1000 
     1001    int result = statement.step(); 
     1002    if (result == SQLResultDone) 
     1003        return false; 
     1004 
     1005    if (result != SQLResultRow) { 
     1006        LOG_ERROR("Could not get the size of the cache group, error \"%s\"", m_database.lastErrorMsg()); 
     1007        return false; 
     1008    } 
     1009 
     1010    *size = statement.getColumnInt64(0); 
     1011    return true; 
     1012} 
     1013 
     1014bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL) 
     1015{ 
     1016    SQLiteTransaction deleteTransaction(m_database); 
     1017    // Check to see if the group is in memory. 
     1018    ApplicationCacheGroup* group = m_cachesInMemory.get(manifestURL); 
     1019    if (group) 
     1020        cacheGroupMadeObsolete(group); 
     1021    else { 
     1022        // The cache group is not in memory, so remove it from the disk. 
     1023        openDatabase(false); 
     1024        if (!m_database.isOpen()) 
     1025            return false; 
     1026 
     1027        SQLiteStatement idStatement(m_database, "SELECT id FROM CacheGroups WHERE manifestURL=?"); 
     1028        if (idStatement.prepare() != SQLResultOk) 
     1029            return false; 
     1030 
     1031        idStatement.bindText(1, manifestURL); 
     1032 
     1033        int result = idStatement.step(); 
     1034        if (result == SQLResultDone) 
     1035            return false; 
     1036 
     1037        if (result != SQLResultRow) { 
     1038            LOG_ERROR("Could not load cache group id, error \"%s\"", m_database.lastErrorMsg()); 
     1039            return false; 
     1040        } 
     1041 
     1042        int64_t groupId = idStatement.getColumnInt64(0); 
     1043 
     1044        SQLiteStatement cacheStatement(m_database, "DELETE FROM Caches WHERE cacheGroup=?"); 
     1045        if (cacheStatement.prepare() != SQLResultOk) 
     1046            return false; 
     1047 
     1048        SQLiteStatement groupStatement(m_database, "DELETE FROM CacheGroups WHERE id=?"); 
     1049        if (groupStatement.prepare() != SQLResultOk) 
     1050            return false; 
     1051 
     1052        cacheStatement.bindInt64(1, groupId); 
     1053        executeStatement(cacheStatement); 
     1054        groupStatement.bindInt64(1, groupId); 
     1055        executeStatement(groupStatement); 
     1056    } 
     1057 
     1058    deleteTransaction.commit(); 
     1059    return true; 
     1060} 
     1061 
     1062void ApplicationCacheStorage::vacuumDatabaseFile() 
     1063{ 
     1064    m_database.runVacuumCommand(); 
     1065} 
     1066 
     1067void ApplicationCacheStorage::checkForMaxSizeReached() 
     1068{ 
     1069    if (m_database.lastError() == SQLResultFull) 
     1070        m_isMaximumSizeReached = true; 
     1071} 
     1072 
     1073ApplicationCacheStorage::ApplicationCacheStorage()  
     1074    : m_maximumSize(INT_MAX) 
     1075    , m_isMaximumSizeReached(false) 
     1076{ 
     1077} 
     1078 
    8851079ApplicationCacheStorage& cacheStorage() 
    8861080{ 
  • trunk/WebCore/loader/appcache/ApplicationCacheStorage.h

    r44943 r46344  
    4141class ApplicationCacheResource; 
    4242class KURL; 
    43 class ResourceStorageIDJournal; 
    44      
     43template <class T> 
     44class StorageIDJournal; 
     45 
    4546class ApplicationCacheStorage { 
    4647public: 
     
    4849    const String& cacheDirectory() const; 
    4950     
     51    void setMaximumSize(int64_t size); 
     52    int64_t maximumSize() const; 
     53    bool isMaximumSizeReached() const; 
     54    int64_t spaceNeeded(int64_t cacheToSave); 
     55 
    5056    ApplicationCacheGroup* cacheGroupForURL(const KURL&); // Cache to load a main resource from. 
    5157    ApplicationCacheGroup* fallbackCacheGroupForURL(const KURL&); // Cache that has a fallback entry to load a main resource from if normal loading fails. 
     
    5662         
    5763    bool storeNewestCache(ApplicationCacheGroup*); // Updates the cache group, but doesn't remove old cache. 
    58     void store(ApplicationCacheResource*, ApplicationCache*); 
     64    bool store(ApplicationCacheResource*, ApplicationCache*); 
    5965    bool storeUpdatedType(ApplicationCacheResource*, ApplicationCache*); 
    6066 
     
    6672    static bool storeCopyOfCache(const String& cacheDirectory, ApplicationCache*); 
    6773 
     74    bool manifestURLs(Vector<KURL>* urls); 
     75    bool cacheGroupSize(const String& manifestURL, int64_t* size); 
     76    bool deleteCacheGroup(const String& manifestURL); 
     77    void vacuumDatabaseFile(); 
    6878private: 
     79    ApplicationCacheStorage(); 
    6980    PassRefPtr<ApplicationCache> loadCache(unsigned storageID); 
    7081    ApplicationCacheGroup* loadCacheGroup(const KURL& manifestURL); 
    7182     
    72     bool store(ApplicationCacheGroup*); 
     83    typedef StorageIDJournal<ApplicationCacheResource> ResourceStorageIDJournal; 
     84    typedef StorageIDJournal<ApplicationCacheGroup> GroupStorageIDJournal; 
     85 
     86    bool store(ApplicationCacheGroup*, GroupStorageIDJournal*); 
    7387    bool store(ApplicationCache*, ResourceStorageIDJournal*); 
    7488    bool store(ApplicationCacheResource*, unsigned cacheStorageID); 
     
    8296    bool executeStatement(SQLiteStatement&); 
    8397    bool executeSQLCommand(const String&); 
     98 
     99    void checkForMaxSizeReached(); 
    84100     
    85101    String m_cacheDirectory; 
     102    String m_cacheFile; 
     103 
     104    int64_t m_maximumSize; 
     105    bool m_isMaximumSizeReached; 
    86106 
    87107    SQLiteDatabase m_database; 
     
    93113    typedef HashMap<String, ApplicationCacheGroup*> CacheGroupMap; 
    94114    CacheGroupMap m_cachesInMemory; // Excludes obsolete cache groups. 
     115 
     116    friend ApplicationCacheStorage& cacheStorage(); 
    95117}; 
    96118  
  • trunk/WebCore/page/ChromeClient.h

    r45991 r46344  
    140140#endif 
    141141 
     142#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     143        // Callback invoked when the application cache fails to save a cache object 
     144        // because storing it would grow the database file past its defined maximum 
     145        // size or past the amount of free space on the device.  
     146        // The chrome client would need to take some action such as evicting some 
     147        // old caches. 
     148        virtual void reachedMaxAppCacheSize(int64_t spaceNeeded) = 0; 
     149#endif 
     150 
    142151#if ENABLE(DASHBOARD_SUPPORT) 
    143152        virtual void dashboardRegionsChanged(); 
  • trunk/WebCore/platform/sql/SQLiteDatabase.cpp

    r45487 r46344  
    149149 
    150150    return m_pageSize; 
     151} 
     152 
     153int64_t SQLiteDatabase::freeSpaceSize() 
     154{ 
     155    MutexLocker locker(m_authorizerLock); 
     156    enableAuthorizer(false); 
     157    // Note: freelist_count was added in SQLite 3.4.1. 
     158    SQLiteStatement statement(*this, "PRAGMA freelist_count"); 
     159    int64_t size = statement.getColumnInt64(0) * pageSize(); 
     160 
     161    enableAuthorizer(true); 
     162    return size; 
    151163} 
    152164 
  • trunk/WebCore/platform/sql/SQLiteDatabase.h

    r36054 r46344  
    8484    void setMaximumSize(int64_t); 
    8585     
     86    // Gets the number of unused bytes in the database file. 
     87    int64_t freeSpaceSize(); 
     88 
    8689    // The SQLite SYNCHRONOUS pragma can be either FULL, NORMAL, or OFF 
    8790    // FULL - Any writing calls to the DB block until the data is actually on the disk surface 
  • trunk/WebKit/ChangeLog

    r46016 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        ApplicationCache should have size limit 
     4        https://bugs.webkit.org/show_bug.cgi?id=22700 
     5         
     6        Updated the project after adding WebApplicationCache.h/mm 
     7 
     8        * WebKit.xcodeproj/project.pbxproj: 
     9 
    1102009-07-16  Maxime Simon  <simon.maxime@gmail.com> 
    211 
  • trunk/WebKit/WebKit.xcodeproj/project.pbxproj

    r45719 r46344  
    309309                AB9FBBBB0F8582B0006ADC43 /* WebDOMOperationsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = AB9FBBBA0F8582B0006ADC43 /* WebDOMOperationsInternal.h */; }; 
    310310                ABDDF20D08EB0DDC001E1241 /* WebDownloadInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDF20C08EB0DDC001E1241 /* WebDownloadInternal.h */; }; 
     311                B6CE5C24100BC5CE00219936 /* WebApplicationCache.mm in Sources */ = {isa = PBXBuildFile; fileRef = B68049720FFBCEC1009F7F62 /* WebApplicationCache.mm */; }; 
     312                B6CE5C25100BC5F500219936 /* WebApplicationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = B68049710FFBCEC1009F7F62 /* WebApplicationCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; 
    311313                BC2E464D0FD8A96800A9D9DE /* WebViewData.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2E464B0FD8A96800A9D9DE /* WebViewData.h */; }; 
    312314                BC2E464E0FD8A96800A9D9DE /* WebViewData.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC2E464C0FD8A96800A9D9DE /* WebViewData.mm */; }; 
     
    565567                AB9FBBBA0F8582B0006ADC43 /* WebDOMOperationsInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebDOMOperationsInternal.h; sourceTree = "<group>"; }; 
    566568                ABDDF20C08EB0DDC001E1241 /* WebDownloadInternal.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = WebDownloadInternal.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; }; 
     569                B68049710FFBCEC1009F7F62 /* WebApplicationCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebApplicationCache.h; sourceTree = "<group>"; }; 
     570                B68049720FFBCEC1009F7F62 /* WebApplicationCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebApplicationCache.mm; sourceTree = "<group>"; }; 
    567571                BC2E464B0FD8A96800A9D9DE /* WebViewData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewData.h; sourceTree = "<group>"; }; 
    568572                BC2E464C0FD8A96800A9D9DE /* WebViewData.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebViewData.mm; sourceTree = "<group>"; }; 
     
    11341138                                14D8252E0AF955090004F057 /* WebChromeClient.mm */, 
    11351139                                065AD5A10B0C32C7005A2B1D /* WebContextMenuClient.h */, 
     1140                                B68049710FFBCEC1009F7F62 /* WebApplicationCache.h */, 
     1141                                B68049720FFBCEC1009F7F62 /* WebApplicationCache.mm */, 
    11361142                                065AD5A20B0C32C7005A2B1D /* WebContextMenuClient.mm */, 
    11371143                                A70936AD0B5608DC00CDB48E /* WebDragClient.h */, 
     
    12671273                                1AAF5CEE0EDDE1FE008D883D /* NetscapePluginInstanceProxy.h in Headers */, 
    12681274                                1A2DBE9F0F251E3A0036F8A6 /* ProxyInstance.h in Headers */, 
     1275                                B6CE5C25100BC5F500219936 /* WebApplicationCache.h in Headers */, 
    12691276                                9398109A0824BF01008DF038 /* WebArchive.h in Headers */, 
    12701277                                5DE92FEF0BD7017E0059A5FD /* WebAssertions.h in Headers */, 
     
    16571664                                1CCFFD130B1F81F2002EE926 /* OldWebAssertions.c in Sources */, 
    16581665                                1A2DBEA00F251E3A0036F8A6 /* ProxyInstance.mm in Sources */, 
     1666                                B6CE5C24100BC5CE00219936 /* WebApplicationCache.mm in Sources */, 
    16591667                                9398111D0824BF01008DF038 /* WebArchive.mm in Sources */, 
    16601668                                939810CF0824BF01008DF038 /* WebAuthenticationPanel.m in Sources */, 
  • trunk/WebKit/gtk/ChangeLog

    r46319 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        Reviewed by Anders Carlsson. 
     4 
     5        ApplicationCache should have size limit 
     6        https://bugs.webkit.org/show_bug.cgi?id=22700 
     7 
     8        * WebCoreSupport/ChromeClientGtk.cpp: 
     9        (WebKit::ChromeClient::reachedMaxAppCacheSize): 
     10        Adds empty implementation of reachedMaxAppCacheSize. 
     11        * WebCoreSupport/ChromeClientGtk.h: 
     12 
    1132009-07-23  Jan Michael Alonzo  <jmalonzo@webkit.org> 
    214 
  • trunk/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp

    r46123 r46344  
    470470#endif 
    471471 
     472#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     473void ChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) 
     474{ 
     475    // FIXME: Free some space. 
     476    notImplemented(); 
     477} 
     478#endif 
     479 
    472480void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) 
    473481{ 
  • trunk/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h

    r45991 r46344  
    101101        virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String&); 
    102102#endif 
     103#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     104        virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); 
     105#endif 
    103106        virtual void runOpenPanel(WebCore::Frame*, PassRefPtr<WebCore::FileChooser>); 
    104107 
  • trunk/WebKit/mac/ChangeLog

    r46300 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        Reviewed by Anders Carlsson. 
     4 
     5        ApplicationCache should have size limit 
     6        https://bugs.webkit.org/show_bug.cgi?id=22700 
     7 
     8        Adds the WebApplicationCache class that is 
     9        used by the DumpRenderTree test application to 
     10        configure the Application Cache maximum size. 
     11 
     12        * WebCoreSupport/WebApplicationCache.h: Added. 
     13        * WebCoreSupport/WebApplicationCache.mm: Added. 
     14        * WebCoreSupport/WebChromeClient.h: 
     15        * WebCoreSupport/WebChromeClient.mm: 
     16        (WebChromeClient::reachedMaxAppCacheSize): 
     17        Adds empty implementation of the reachedMaxAppCacheSize callback. 
     18        * WebKit.exp: 
     19 
    1202009-07-23  Darin Adler  <darin@apple.com> 
    221 
  • trunk/WebKit/mac/WebCoreSupport/WebChromeClient.h

    r45991 r46344  
    108108    virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String& databaseName); 
    109109#endif 
     110#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     111    virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); 
     112#endif 
    110113    virtual void populateVisitedLinks(); 
    111114 
  • trunk/WebKit/mac/WebCoreSupport/WebChromeClient.mm

    r45991 r46344  
    537537} 
    538538#endif 
     539 
     540#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     541void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) 
     542{ 
     543    // FIXME: Free some space. 
     544} 
     545#endif 
    539546     
    540547void WebChromeClient::populateVisitedLinks() 
  • trunk/WebKit/mac/WebKit.exp

    r45923 r46344  
     1.objc_class_name_WebApplicationCache 
    12.objc_class_name_WebArchive 
    23.objc_class_name_WebBackForwardList 
  • trunk/WebKit/qt/ChangeLog

    r46267 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        Reviewed by Anders Carlsson. 
     4 
     5        ApplicationCache should have size limit 
     6        https://bugs.webkit.org/show_bug.cgi?id=22700 
     7 
     8        * WebCoreSupport/ChromeClientQt.cpp: 
     9        (WebCore::ChromeClientQt::reachedMaxAppCacheSize): 
     10        Adds empty implementation of the reachedMaxAppCacheSize callback. 
     11        * WebCoreSupport/ChromeClientQt.h: 
     12 
    1132009-07-23  Laszlo Gombos  <laszlo.1.gombos@nokia.com> 
    214 
  • trunk/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp

    r46000 r46344  
    402402#endif 
    403403 
     404#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     405void ChromeClientQt::reachedMaxAppCacheSize(int64_t spaceNeeded) 
     406{ 
     407    // FIXME: Free some space. 
     408    notImplemented(); 
     409} 
     410#endif 
     411 
    404412void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser) 
    405413{ 
  • trunk/WebKit/qt/WebCoreSupport/ChromeClientQt.h

    r45991 r46344  
    117117        virtual void exceededDatabaseQuota(Frame*, const String&); 
    118118#endif 
     119#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     120        virtual int64_t maxAppCacheSize(); 
     121        virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); 
     122#endif 
    119123        virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); 
    120124 
  • trunk/WebKit/win/ChangeLog

    r46325 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        Reviewed by Anders Carlsson. 
     4 
     5        ApplicationCache should have size limit 
     6        https://bugs.webkit.org/show_bug.cgi?id=22700 
     7 
     8        * WebCoreSupport/WebChromeClient.cpp: 
     9        (WebChromeClient::reachedMaxAppCacheSize): 
     10        Adds empty implementation of the reachedMaxAppCacheSize callback. 
     11        * WebCoreSupport/WebChromeClient.h: 
     12 
    1132009-07-23  Brady Eidson  <beidson@apple.com> 
    214 
  • trunk/WebKit/win/WebCoreSupport/WebChromeClient.cpp

    r45991 r46344  
    544544#endif 
    545545 
     546#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     547#include "ApplicationCacheStorage.h" 
     548void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) 
     549{ 
     550    // FIXME: Free some space. 
     551    notImplemented(); 
     552} 
     553#endif 
     554 
    546555void WebChromeClient::populateVisitedLinks() 
    547556{ 
  • trunk/WebKit/win/WebCoreSupport/WebChromeClient.h

    r45991 r46344  
    107107#endif 
    108108 
     109#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     110    virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); 
     111#endif 
     112 
    109113    virtual void populateVisitedLinks(); 
    110114 
  • trunk/WebKit/wx/ChangeLog

    r46193 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        Reviewed by Anders Carlsson. 
     4 
     5        ApplicationCache should have size limit 
     6        https://bugs.webkit.org/show_bug.cgi?id=22700 
     7  
     8        * WebKitSupport/ChromeClientWx.cpp: 
     9        (WebCore::ChromeClientWx::reachedMaxAppCacheSize): 
     10        Adds empty implementation of the reachedMaxAppCacheSize callback. 
     11        * WebKitSupport/ChromeClientWx.h: 
     12 
    1132009-07-21  Kevin Ollivier  <kevino@theolliviers.com> 
    214 
  • trunk/WebKit/wx/WebKitSupport/ChromeClientWx.cpp

    r45991 r46344  
    385385#endif 
    386386 
     387#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     388void ChromeClientWx::reachedMaxAppCacheSize(int64_t spaceNeeded) 
     389{ 
     390    notImplemented(); 
     391} 
     392#endif 
     393 
    387394void ChromeClientWx::scroll(const IntSize&, const IntRect&, const IntRect&) 
    388395{ 
  • trunk/WebKit/wx/WebKitSupport/ChromeClientWx.h

    r45991 r46344  
    117117    virtual void exceededDatabaseQuota(Frame*, const String&); 
    118118#endif 
     119 
     120#if ENABLE(OFFLINE_WEB_APPLICATIONS) 
     121    virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); 
     122#endif 
     123 
    119124    virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); 
    120125 
  • trunk/WebKitTools/ChangeLog

    r46341 r46344  
     12009-07-24  Andrei Popescu  <andreip@google.com> 
     2 
     3        Reviewed by Anders Carlsson. 
     4 
     5        ApplicationCache should have size limit 
     6        https://bugs.webkit.org/show_bug.cgi?id=22700 
     7 
     8        Adds a new method on the LayoutTestController that 
     9        allows a JS unit test to configure the maximum size 
     10        of the Application Cache. 
     11 
     12        * DumpRenderTree/LayoutTestController.cpp: 
     13        (setAppCacheMaximumSizeCallback): 
     14        (LayoutTestController::staticFunctions): 
     15        * DumpRenderTree/LayoutTestController.h: 
     16        * DumpRenderTree/gtk/LayoutTestControllerGtk.cpp: 
     17        (LayoutTestController::setAppCacheMaximumSize): 
     18        * DumpRenderTree/mac/LayoutTestControllerMac.mm: 
     19        (LayoutTestController::setAppCacheMaximumSize): 
     20        * DumpRenderTree/win/LayoutTestControllerWin.cpp: 
     21        (LayoutTestController::setAppCacheMaximumSize): 
     22        * DumpRenderTree/wx/LayoutTestControllerWx.cpp: 
     23        (LayoutTestController::setAppCacheMaximumSize): 
     24 
    1252009-07-24  Adam Barth  <abarth@webkit.org> 
    226 
  • trunk/WebKitTools/DumpRenderTree/LayoutTestController.cpp

    r46308 r46344  
    487487 
    488488    return JSValueMakeUndefined(context); 
     489} 
     490 
     491static JSValueRef setAppCacheMaximumSizeCallback(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 
     492{ 
     493    // Has mac implementation 
     494    if (argumentCount < 1) 
     495        return JSValueMakeUndefined(context); 
     496 
     497    LayoutTestController* controller = static_cast<LayoutTestController*>(JSObjectGetPrivate(thisObject)); 
     498 
     499    double size = JSValueToNumber(context, arguments[0], NULL); 
     500    if (!isnan(size)) 
     501        controller->setAppCacheMaximumSize(static_cast<unsigned long long>(size)); 
     502         
     503    return JSValueMakeUndefined(context); 
     504 
    489505} 
    490506 
     
    920936        { "setAcceptsEditing", setAcceptsEditingCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
    921937        { "setAuthorAndUserStylesEnabled", setAuthorAndUserStylesEnabledCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
     938        { "setAppCacheMaximumSize", setAppCacheMaximumSizeCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },  
    922939        { "setCallCloseOnWebViews", setCallCloseOnWebViewsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
    923940        { "setCanOpenWindows", setCanOpenWindowsCallback, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete }, 
  • trunk/WebKitTools/DumpRenderTree/LayoutTestController.h

    r46308 r46344  
    6161    void queueReload(); 
    6262    void setAcceptsEditing(bool acceptsEditing); 
     63    void setAppCacheMaximumSize(unsigned long long quota); 
    6364    void setAuthorAndUserStylesEnabled(bool); 
    6465    void setCacheModel(int); 
  • trunk/WebKitTools/DumpRenderTree/gtk/LayoutTestControllerGtk.cpp

    r45801 r46344  
    333333} 
    334334 
     335void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) 
     336{ 
     337    // FIXME: implement 
     338} 
     339 
    335340bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId) 
    336341{     
  • trunk/WebKitTools/DumpRenderTree/mac/LayoutTestControllerMac.mm

    r46340 r46344  
    4141#import <WebKit/DOMDocument.h> 
    4242#import <WebKit/DOMElement.h> 
     43#import <WebKit/WebApplicationCache.h> 
    4344#import <WebKit/WebBackForwardList.h> 
    4445#import <WebKit/WebDatabaseManagerPrivate.h> 
     
    192193} 
    193194 
     195void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) 
     196{ 
     197    [WebApplicationCache setMaximumSize:size]; 
     198} 
     199 
    194200void LayoutTestController::setAuthorAndUserStylesEnabled(bool flag) 
    195201{ 
  • trunk/WebKitTools/DumpRenderTree/win/LayoutTestControllerWin.cpp

    r44847 r46344  
    700700} 
    701701 
     702void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) 
     703{ 
     704    printf("ERROR: LayoutTestController::setAppCacheMaximumSize() not implemented\n"); 
     705} 
     706 
    702707bool LayoutTestController::pauseAnimationAtTimeOnElementWithId(JSStringRef animationName, double time, JSStringRef elementId) 
    703708{ 
  • trunk/WebKitTools/DumpRenderTree/wx/LayoutTestControllerWx.cpp

    r44846 r46344  
    207207} 
    208208 
     209void LayoutTestController::setAppCacheMaximumSize(unsigned long long size) 
     210{ 
     211    // FIXME: implement 
     212} 
     213 
    209214unsigned LayoutTestController::numberOfActiveAnimations() const 
    210215{