Changeset 177294 in webkit


Ignore:
Timestamp:
Dec 15, 2014 11:25:23 AM (9 years ago)
Author:
Antti Koivisto
Message:

WebKit level persistent caching
https://bugs.webkit.org/show_bug.cgi?id=30322

Reviewed by Sam Weinig.

Source/WebCore:

Test: http/tests/cache/disk-cache-validation.html

  • WebCore.exp.in:
  • inspector/InspectorResourceAgent.cpp:

(WebCore::buildObjectForResourceResponse):

  • platform/network/ResourceResponseBase.cpp:

(WebCore::ResourceResponseBase::ResourceResponseBase):
(WebCore::ResourceResponseBase::source):
(WebCore::ResourceResponseBase::setSource):
(WebCore::ResourceResponseBase::wasCached): Deleted.
(WebCore::ResourceResponseBase::setWasCached): Deleted.

Replace wasCached bit with Source enum.
This is useful for testing.

  • platform/network/ResourceResponseBase.h:

(WebCore::ResourceResponseBase::containsCertificateInfo):
(WebCore::ResourceResponseBase::encode):
(WebCore::ResourceResponseBase::decode):

  • testing/Internals.cpp:

(WebCore::Internals::xhrResponseSource):
(WebCore::Internals::clearMemoryCache):

  • testing/Internals.h:
  • testing/Internals.idl:

Testing support.

  • xml/XMLHttpRequest.h:

Source/WebKit2:

We can improve performance and open new optimization possibilities by bringing network caching into WebKit.

This patch implements an experimental HTTP cache living in the network process.

The main classes are:

NetworkCache

  • Implements HTTP cache validation logic including Vary header
  • Initially non-range GET only
  • Fast serialization using WebKit types (ResourcesResponse etc) instead of native network layer types

NetworkCacheKey

  • Unique identifier for cache entries
  • Keyed on method/partition/URL

NetworkCacheStorage

  • Storage backend
  • dispatch-IO based implementation (generic posix implementation wouldn't be difficult)
  • File system only (no SQLite or similar)
  • One file per resource containing both header and body data
  • Zero persistent global metadata
  • Bloom filter for fast fail

NetworkCacheEncoder/Decoder

  • Serializisation support with integrity verification.

The code is behind the NETWORK_CACHE feature flag and requires network process to be enabled to use.

This patch does not enable the feature yet by default.

Test: http/tests/cache/disk-cache-validation.html

  • NetworkProcess/cache/NetworkCache.cpp: Added.
  • NetworkProcess/cache/NetworkCache.h: Added.
  • NetworkProcess/cache/NetworkCacheKey.cpp: Added.
  • NetworkProcess/cache/NetworkCacheKey.h: Added.
  • NetworkProcess/cache/NetworkCacheStorage.h: Added.
  • NetworkProcess/cache/NetworkCacheStorage.mm: Added.
  • NetworkProcess/cocoa/NetworkProcessCocoa.mm:

(WebKit::NetworkProcess::platformInitializeNetworkProcessCocoa):
(WebKit::NetworkProcess::platformSetCacheModel):

  • NetworkProcess/ios/NetworkProcessIOS.mm:

(WebKit::NetworkProcess::clearCacheForAllOrigins):

  • NetworkProcess/mac/NetworkProcessMac.mm:

(WebKit::NetworkProcess::clearCacheForAllOrigins):

  • NetworkProcess/mac/NetworkResourceLoaderMac.mm:

(WebKit::tryGetShareableHandleFromCFData):

  • Platform/Logging.h:
  • WebKit2.xcodeproj/project.pbxproj:
  • config.h:

LayoutTests:

Add a cache validation test. The test generates large number of validation header permutations.

  • TestExpectations: Skipped until the feature is enabled.
  • http/tests/cache/disk-cache-validation-expected.txt: Added.
  • http/tests/cache/disk-cache-validation.html: Added.
  • http/tests/cache/resources/cache-test.js: Added.

(getServerDate):
(makeHeaderValue):
(generateTestURL):
(loadResource):
(loadResources):
(printResults):
(runTests):
(mergeFields):
(generateTests):

  • http/tests/cache/resources/generate-response.cgi: Added.
  • platform/mac-mountainlion/TestExpectations: Added.
  • platform/mac-wk1/TestExpectations:
Location:
trunk
Files:
11 added
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r177292 r177294  
     12014-12-15  Antti Koivisto  <antti@apple.com>
     2
     3        WebKit level persistent caching
     4        https://bugs.webkit.org/show_bug.cgi?id=30322
     5
     6        Reviewed by Sam Weinig.
     7
     8        Add a cache validation test. The test generates large number of validation header permutations.
     9
     10        * TestExpectations: Skipped until the feature is enabled.
     11        * http/tests/cache/disk-cache-validation-expected.txt: Added.
     12        * http/tests/cache/disk-cache-validation.html: Added.
     13        * http/tests/cache/resources/cache-test.js: Added.
     14        (getServerDate):
     15        (makeHeaderValue):
     16        (generateTestURL):
     17        (loadResource):
     18        (loadResources):
     19        (printResults):
     20        (runTests):
     21        (mergeFields):
     22        (generateTests):
     23        * http/tests/cache/resources/generate-response.cgi: Added.
     24        * platform/mac-mountainlion/TestExpectations: Added.
     25        * platform/mac-wk1/TestExpectations:
     26
    1272014-12-15  Myles C. Maxfield  <mmaxfield@apple.com>
    228
  • trunk/LayoutTests/TestExpectations

    r177273 r177294  
    329329webkit.org/b/139548 fast/xmlhttprequest/xmlhttprequest-recursive-sync-event.html [ Skip ]
    330330
     331# Network process disk cache is not enabled yet
     332webkit.org/b/30322 http/tests/cache/disk-cache-validation.html [ Skip ]
     333
    331334webkit.org/b/139634 [ Debug ] fast/selectors/matches-backtracking.html [ Slow ]
    332335webkit.org/b/139634 [ Debug ] fast/selectors/nth-child-of-register-requirement.html [ Slow ]
  • trunk/LayoutTests/platform/mac-wk1/TestExpectations

    r177265 r177294  
    8181compositing/iframes/overlapped-nested-iframes.html [ Pass Failure ]
    8282
     83# Disk cache is WK2 only
     84http/tests/cache/disk-cache-validation.html
     85
    8386### END OF (2) Failures without bug reports
    8487########################################
  • trunk/Source/WebCore/ChangeLog

    r177293 r177294  
     12014-12-15  Antti Koivisto  <antti@apple.com>
     2
     3        WebKit level persistent caching
     4        https://bugs.webkit.org/show_bug.cgi?id=30322
     5
     6        Reviewed by Sam Weinig.
     7
     8        Test: http/tests/cache/disk-cache-validation.html
     9
     10        * WebCore.exp.in:
     11        * inspector/InspectorResourceAgent.cpp:
     12        (WebCore::buildObjectForResourceResponse):
     13        * platform/network/ResourceResponseBase.cpp:
     14        (WebCore::ResourceResponseBase::ResourceResponseBase):
     15        (WebCore::ResourceResponseBase::source):
     16        (WebCore::ResourceResponseBase::setSource):
     17        (WebCore::ResourceResponseBase::wasCached): Deleted.
     18        (WebCore::ResourceResponseBase::setWasCached): Deleted.
     19
     20            Replace wasCached bit with Source enum.
     21            This is useful for testing.
     22
     23        * platform/network/ResourceResponseBase.h:
     24        (WebCore::ResourceResponseBase::containsCertificateInfo):
     25        (WebCore::ResourceResponseBase::encode):
     26        (WebCore::ResourceResponseBase::decode):
     27        * testing/Internals.cpp:
     28        (WebCore::Internals::xhrResponseSource):
     29        (WebCore::Internals::clearMemoryCache):
     30        * testing/Internals.h:
     31        * testing/Internals.idl:
     32
     33            Testing support.
     34
     35        * xml/XMLHttpRequest.h:
     36
    1372014-12-15  Andreas Kling  <akling@apple.com>
    238
  • trunk/Source/WebCore/WebCore.exp.in

    r177259 r177294  
    899899__ZN7WebCore20ResourceResponseBase24setExpectedContentLengthEx
    900900__ZN7WebCore20ResourceResponseBase6setURLERKNS_3URLE
     901__ZN7WebCore20ResourceResponseBase9setSourceENS0_6SourceE
    901902__ZN7WebCore20ResourceResponseBaseC2Ev
    902903__ZN7WebCore20StorageNamespaceImpl29createSessionStorageNamespaceEj
     
    18921893__ZNK7WebCore20ResourceResponseBase3urlEv
    18931894__ZNK7WebCore20ResourceResponseBase6isHTTPEv
     1895__ZNK7WebCore20ResourceResponseBase6sourceEv
    18941896__ZNK7WebCore20ResourceResponseBase8lazyInitENS0_9InitLevelE
    18951897__ZNK7WebCore20ResourceResponseBase8mimeTypeEv
  • trunk/Source/WebCore/inspector/InspectorResourceAgent.cpp

    r176450 r177294  
    242242        .setConnectionId(response.connectionID());
    243243
    244     responseObject->setFromDiskCache(response.wasCached());
     244    responseObject->setFromDiskCache(response.source() == ResourceResponse::Source::DiskCache || response.source() == ResourceResponse::Source::DiskCacheAfterValidation);
    245245    responseObject->setTiming(buildObjectForTiming(response.resourceLoadTiming(), loader));
    246246
  • trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp

    r173426 r177294  
    5555    , m_expires(0)
    5656    , m_lastModified(0)
    57     , m_wasCached(false)
    5857    , m_connectionReused(false)
    5958    , m_isNull(true)
     
    6665    , m_cacheControlContainsNoStore(false)
    6766    , m_cacheControlContainsMustRevalidate(false)
     67    , m_source(Source::Unknown)
    6868{
    6969}
     
    8282    , m_expires(0)
    8383    , m_lastModified(0)
    84     , m_wasCached(false)
    8584    , m_connectionReused(false)
    8685    , m_isNull(false)
     
    9392    , m_cacheControlContainsNoStore(false)
    9493    , m_cacheControlContainsMustRevalidate(false)
     94    , m_source(Source::Unknown)
    9595{
    9696}
     
    518518}
    519519 
    520 bool ResourceResponseBase::wasCached() const
    521 {
    522     lazyInit(AllFields);
    523 
    524     return m_wasCached;
    525 }
    526 
    527 void ResourceResponseBase::setWasCached(bool value)
    528 {
    529     m_wasCached = value;
     520ResourceResponseBase::Source ResourceResponseBase::source() const
     521{
     522    lazyInit(AllFields);
     523
     524    return m_source;
     525}
     526
     527void ResourceResponseBase::setSource(Source source)
     528{
     529    m_source = source;
    530530}
    531531
  • trunk/Source/WebCore/platform/network/ResourceResponseBase.h

    r173423 r177294  
    9595
    9696    void includeCertificateInfo() const;
     97    bool containsCertificateInfo() const { return m_includesCertificateInfo; }
    9798    CertificateInfo certificateInfo() const;
    9899   
     
    115116    void setConnectionReused(bool);
    116117
    117     bool wasCached() const;
    118     void setWasCached(bool);
     118    enum class Source { Unknown, Network, DiskCache, DiskCacheAfterValidation };
     119    Source source() const;
     120    void setSource(Source);
    119121
    120122    ResourceLoadTiming& resourceLoadTiming() const { return m_resourceLoadTiming; }
     
    173175
    174176public:
    175     bool m_wasCached : 1;
    176177    bool m_connectionReused : 1;
    177178
     
    192193    mutable bool m_cacheControlContainsNoStore : 1;
    193194    mutable bool m_cacheControlContainsMustRevalidate : 1;
     195
     196    Source m_source;
    194197};
    195198
     
    217220    if (m_includesCertificateInfo)
    218221        encoder << m_certificateInfo;
     222    encoder.encodeEnum(m_source);
    219223}
    220224
     
    257261            return false;
    258262    }
     263    if (!decoder.decodeEnum(response.m_source))
     264        return false;
    259265    response.m_isNull = false;
    260266
  • trunk/Source/WebCore/testing/Internals.cpp

    r177135 r177294  
    3232#include "ApplicationCacheStorage.h"
    3333#include "BackForwardController.h"
     34#include "CachedImage.h"
    3435#include "CachedResourceLoader.h"
    3536#include "Chrome.h"
     
    5354#include "FrameView.h"
    5455#include "HTMLIFrameElement.h"
     56#include "HTMLImageElement.h"
    5557#include "HTMLInputElement.h"
    5658#include "HTMLNames.h"
     
    103105#include "WebConsoleAgent.h"
    104106#include "WorkerThread.h"
     107#include "XMLHttpRequest.h"
    105108#include <bytecode/CodeBlock.h>
    106109#include <inspector/InspectorAgentBase.h>
     
    385388}
    386389
     390String Internals::xhrResponseSource(XMLHttpRequest* xhr)
     391{
     392    if (!xhr)
     393        return "Null xhr";
     394    if (xhr->resourceResponse().isNull())
     395        return "Null response";
     396    switch (xhr->resourceResponse().source()) {
     397    case ResourceResponse::Source::Unknown:
     398        return "Unknown";
     399    case ResourceResponse::Source::Network:
     400        return "Network";
     401    case ResourceResponse::Source::DiskCache:
     402        return "Disk cache";
     403    case ResourceResponse::Source::DiskCacheAfterValidation:
     404        return "Disk cache after validation";
     405    }
     406    ASSERT_NOT_REACHED();
     407    return "Error";
     408}
     409
     410void Internals::clearMemoryCache()
     411{
     412    memoryCache().evictResources();
     413}
    387414
    388415Node* Internals::treeScopeRootNode(Node* node, ExceptionCode& ec)
  • trunk/Source/WebCore/testing/Internals.h

    r177135 r177294  
    6363class TimeRanges;
    6464class TypeConversions;
     65class XMLHttpRequest;
    6566
    6667typedef int ExceptionCode;
     
    8384    bool isPreloaded(const String& url);
    8485    bool isLoadingFromMemoryCache(const String& url);
     86    String xhrResponseSource(XMLHttpRequest*);
     87    void clearMemoryCache();
    8588
    8689    PassRefPtr<CSSComputedStyleDeclaration> computedStyleIncludingVisitedInfo(Node*, ExceptionCode&) const;
  • trunk/Source/WebCore/testing/Internals.idl

    r177135 r177294  
    4343    boolean isPreloaded(DOMString url);
    4444    boolean isLoadingFromMemoryCache(DOMString url);
     45    DOMString xhrResponseSource(XMLHttpRequest xhr);
     46    void clearMemoryCache();
    4547
    4648    [RaisesException] CSSStyleDeclaration computedStyleIncludingVisitedInfo(Node node);
  • trunk/Source/WebCore/xml/XMLHttpRequest.h

    r175053 r177294  
    145145    XMLHttpRequestUpload* optionalUpload() const { return m_upload.get(); }
    146146
     147    const ResourceResponse& resourceResponse() const { return m_response; }
     148
    147149    DEFINE_ATTRIBUTE_EVENT_LISTENER(readystatechange);
    148150    DEFINE_ATTRIBUTE_EVENT_LISTENER(abort);
  • trunk/Source/WebKit2/CMakeLists.txt

    r177125 r177294  
    44    "${WEBKIT2_DIR}/NetworkProcess"
    55    "${WEBKIT2_DIR}/NetworkProcess/FileAPI"
     6    "${WEBKIT2_DIR}/NetworkProcess/cache"
    67    "${WEBKIT2_DIR}/Platform"
    78    "${WEBKIT2_DIR}/Platform/IPC"
  • trunk/Source/WebKit2/ChangeLog

    r177291 r177294  
     12014-12-15  Antti Koivisto  <antti@apple.com>
     2
     3        WebKit level persistent caching
     4        https://bugs.webkit.org/show_bug.cgi?id=30322
     5
     6        Reviewed by Sam Weinig.
     7
     8        We can improve performance and open new optimization possibilities by bringing network caching into WebKit.
     9
     10        This patch implements an experimental HTTP cache living in the network process.
     11
     12        The main classes are:
     13
     14        NetworkCache
     15            - Implements HTTP cache validation logic including Vary header
     16            - Initially non-range GET only
     17            - Fast serialization using WebKit types (ResourcesResponse etc) instead of native network layer types
     18
     19        NetworkCacheKey
     20            - Unique identifier for cache entries
     21            - Keyed on method/partition/URL
     22
     23        NetworkCacheStorage
     24            - Storage backend
     25            - dispatch-IO based implementation (generic posix implementation wouldn't be difficult)
     26            - File system only (no SQLite or similar)
     27            - One file per resource containing both header and body data
     28            - Zero persistent global metadata
     29            - Bloom filter for fast fail
     30
     31        NetworkCacheEncoder/Decoder
     32            - Serializisation support with integrity verification.
     33
     34        The code is behind the NETWORK_CACHE feature flag and requires network process to be enabled to use.
     35
     36        This patch does not enable the feature yet by default.
     37
     38        Test: http/tests/cache/disk-cache-validation.html
     39
     40        * NetworkProcess/cache/NetworkCache.cpp: Added.
     41        * NetworkProcess/cache/NetworkCache.h: Added.
     42        * NetworkProcess/cache/NetworkCacheKey.cpp: Added.
     43        * NetworkProcess/cache/NetworkCacheKey.h: Added.
     44        * NetworkProcess/cache/NetworkCacheStorage.h: Added.
     45        * NetworkProcess/cache/NetworkCacheStorage.mm: Added.
     46        * NetworkProcess/cocoa/NetworkProcessCocoa.mm:
     47        (WebKit::NetworkProcess::platformInitializeNetworkProcessCocoa):
     48        (WebKit::NetworkProcess::platformSetCacheModel):
     49        * NetworkProcess/ios/NetworkProcessIOS.mm:
     50        (WebKit::NetworkProcess::clearCacheForAllOrigins):
     51        * NetworkProcess/mac/NetworkProcessMac.mm:
     52        (WebKit::NetworkProcess::clearCacheForAllOrigins):
     53        * NetworkProcess/mac/NetworkResourceLoaderMac.mm:
     54        (WebKit::tryGetShareableHandleFromCFData):
     55        * Platform/Logging.h:
     56        * WebKit2.xcodeproj/project.pbxproj:
     57        * config.h:
     58
    1592014-12-15  Gavin Barraclough  <barraclough@apple.com>
    260
  • trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.cpp

    r176947 r177294  
    3333#include "Logging.h"
    3434#include "NetworkBlobRegistry.h"
     35#include "NetworkCache.h"
    3536#include "NetworkConnectionToWebProcess.h"
    3637#include "NetworkProcess.h"
     
    4546#include <WebCore/BlobDataFileReference.h>
    4647#include <WebCore/CertificateInfo.h>
     48#include <WebCore/HTTPHeaderNames.h>
    4749#include <WebCore/NotImplemented.h>
    4850#include <WebCore/ResourceHandle.h>
     
    131133        return;
    132134
     135    m_currentRequest = originalRequest();
     136
     137#if ENABLE(NETWORK_CACHE)
     138    if (!NetworkCache::shared().isEnabled() || sessionID().isEphemeral()) {
     139        startNetworkLoad();
     140        return;
     141    }
     142
     143    RefPtr<NetworkResourceLoader> loader(this);
     144    NetworkCache::shared().retrieve(originalRequest(), [loader](std::unique_ptr<NetworkCache::Entry> entry) {
     145        if (loader->hasOneRef()) {
     146            // The loader has been aborted and is only held alive by this lambda.
     147            return;
     148        }
     149        if (!entry) {
     150            loader->startNetworkLoad();
     151            return;
     152        }
     153        if (loader->m_parameters.needsCertificateInfo && !entry->response.containsCertificateInfo()) {
     154            loader->startNetworkLoad();
     155            return;
     156        }
     157        if (entry->needsRevalidation) {
     158            loader->validateCacheEntry(WTF::move(entry));
     159            return;
     160        }
     161        loader->didRetrieveCacheEntry(WTF::move(entry));
     162    });
     163#else
     164    startNetworkLoad();
     165#endif
     166}
     167
     168void NetworkResourceLoader::startNetworkLoad()
     169{
    133170    m_networkingContext = RemoteNetworkingContext::create(sessionID(), m_parameters.shouldClearReferrerOnHTTPSToHTTPRedirect);
    134171
    135172    consumeSandboxExtensions();
    136 
    137     m_currentRequest = originalRequest();
    138173
    139174    if (isSynchronous() || m_parameters.maximumBufferingTime > 0_ms)
    140175        m_bufferedData = WebCore::SharedBuffer::create();
    141176
     177#if ENABLE(NETWORK_CACHE)
     178    if (NetworkCache::shared().isEnabled())
     179        m_bufferedDataForCache = WebCore::SharedBuffer::create();
     180#endif
     181
    142182    bool shouldSniff = m_parameters.contentSniffingPolicy == SniffContent;
    143     m_handle = ResourceHandle::create(m_networkingContext.get(), m_currentRequest, this, false /* defersLoading */, shouldSniff);
     183    m_handle = ResourceHandle::create(m_networkingContext.get(), m_currentRequest, this, m_defersLoading, shouldSniff);
    144184}
    145185
     
    189229}
    190230
    191 void NetworkResourceLoader::didReceiveResponseAsync(ResourceHandle* handle, const ResourceResponse& response)
    192 {
    193     ASSERT_UNUSED(handle, handle == m_handle);
    194 
     231#if ENABLE(NETWORK_CACHE)
     232static bool isConditionalRequest(const WebCore::ResourceRequest& request)
     233{
     234    if (!request.httpHeaderField(WebCore::HTTPHeaderName::IfNoneMatch).isEmpty())
     235        return true;
     236    if (!request.httpHeaderField(WebCore::HTTPHeaderName::IfModifiedSince).isEmpty())
     237        return true;
     238    return false;
     239}
     240#endif
     241
     242void NetworkResourceLoader::didReceiveResponseAsync(ResourceHandle* handle, const ResourceResponse& receivedResponse)
     243{
     244    ASSERT_UNUSED(handle, handle == m_handle);
     245
     246    m_response = receivedResponse;
     247
     248    m_response.setSource(ResourceResponse::Source::Network);
    195249    if (m_parameters.needsCertificateInfo)
    196         response.includeCertificateInfo();
    197 
    198     if (isSynchronous())
    199         m_synchronousLoadData->response = response;
    200     else {
    201         // For multipart/x-mixed-replace didReceiveResponseAsync gets called multiple times and buffering would require special handling.
    202         if (response.isMultipart())
    203             m_bufferedData = nullptr;
    204 
    205         if (!sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponse(response, m_parameters.isMainResource)))
    206             return;
     250        m_response.includeCertificateInfo();
     251    // For multipart/x-mixed-replace didReceiveResponseAsync gets called multiple times and buffering would require special handling.
     252    if (!isSynchronous() && m_response.isMultipart())
     253        m_bufferedData = nullptr;
     254
     255    bool shouldSendDidReceiveResponse = true;
     256#if ENABLE(NETWORK_CACHE)
     257    if (m_cacheEntryForValidation) {
     258        bool validationSucceeded = m_response.httpStatusCode() == 304; // 304 Not Modified
     259        if (validationSucceeded)
     260            NetworkCache::shared().update(originalRequest(), *m_cacheEntryForValidation, m_response);
     261        if (!validationSucceeded || isConditionalRequest(originalRequest()))
     262            m_cacheEntryForValidation = nullptr;
     263    }
     264    shouldSendDidReceiveResponse = !m_cacheEntryForValidation;
     265#endif
     266
     267    if (shouldSendDidReceiveResponse) {
     268        if (isSynchronous())
     269            m_synchronousLoadData->response = m_response;
     270        else {
     271            if (!sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponse(m_response, m_parameters.isMainResource)))
     272                return;
     273        }
    207274    }
    208275
    209276    // For main resources, the web process is responsible for sending back a NetworkResourceLoader::ContinueDidReceiveResponse message.
    210     if (m_parameters.isMainResource)
     277    bool shouldContinueDidReceiveResponse = !m_parameters.isMainResource;
     278#if ENABLE(NETWORK_CACHE)
     279    shouldContinueDidReceiveResponse = shouldContinueDidReceiveResponse || m_cacheEntryForValidation;
     280#endif
     281    if (!shouldContinueDidReceiveResponse)
    211282        return;
    212283
     
    224295{
    225296    ASSERT_UNUSED(handle, handle == m_handle);
    226 
     297#if ENABLE(NETWORK_CACHE)
     298    ASSERT(!m_cacheEntryForValidation);
     299
     300    if (m_bufferedDataForCache)
     301        m_bufferedDataForCache->append(buffer.get());
     302#endif
    227303    // FIXME: At least on OS X Yosemite we always get -1 from the resource handle.
    228304    unsigned encodedDataLength = reportedEncodedDataLength >= 0 ? reportedEncodedDataLength : buffer->size();
     
    241317{
    242318    ASSERT_UNUSED(handle, handle == m_handle);
     319
     320#if ENABLE(NETWORK_CACHE)
     321    if (NetworkCache::shared().isEnabled()) {
     322        if (m_cacheEntryForValidation) {
     323            // 304 Not Modified
     324            ASSERT(m_response.httpStatusCode() == 304);
     325            LOG(NetworkCache, "(NetworkProcess) revalidated");
     326            didRetrieveCacheEntry(WTF::move(m_cacheEntryForValidation));
     327            return;
     328        }
     329
     330        bool hasCacheableRedirect = WebCore::redirectChainAllowsReuse(m_redirectChainCacheStatus);
     331        if (hasCacheableRedirect && m_redirectChainCacheStatus.status == RedirectChainCacheStatus::CachedRedirection) {
     332            // FIXME: Cache the actual redirects instead of the end result.
     333            double now = currentTime();
     334            double responseEndOfValidity = now + WebCore::computeFreshnessLifetimeForHTTPFamily(m_response, now) - WebCore::computeCurrentAge(m_response, now);
     335            hasCacheableRedirect = responseEndOfValidity <= m_redirectChainCacheStatus.endOfValidity;
     336        }
     337
     338        bool isPrivate = sessionID().isEphemeral();
     339        if (hasCacheableRedirect && !isPrivate)
     340            NetworkCache::shared().store(originalRequest(), m_response, m_bufferedDataForCache.release());
     341    }
     342#endif
    243343
    244344    if (isSynchronous())
     
    259359void NetworkResourceLoader::didFail(ResourceHandle* handle, const ResourceError& error)
    260360{
    261     ASSERT_UNUSED(handle, handle == m_handle);
     361    ASSERT_UNUSED(handle, !handle || handle == m_handle);
     362
     363#if ENABLE(NETWORK_CACHE)
     364    m_cacheEntryForValidation = nullptr;
     365#endif
    262366
    263367    if (isSynchronous()) {
     
    280384    m_currentRequest = request;
    281385
     386#if ENABLE(NETWORK_CACHE)
     387    WebCore::updateRedirectChainStatus(m_redirectChainCacheStatus, redirectResponse);
     388#endif
     389
    282390    if (isSynchronous()) {
    283391        // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
    284392        // This includes at least updating host records, and comparing the current request instead of the original request here.
    285         if (!protocolHostAndPortAreEqual(originalRequest().url(), request.url())) {
     393        if (!protocolHostAndPortAreEqual(originalRequest().url(), m_currentRequest.url())) {
    286394            ASSERT(m_synchronousLoadData->error.isNull());
    287395            m_synchronousLoadData->error = SynchronousLoaderClient::platformBadResponseError();
     
    291399        return;
    292400    }
    293     sendAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(request, redirectResponse));
     401    sendAbortingOnFailure(Messages::WebResourceLoader::WillSendRequest(m_currentRequest, redirectResponse));
    294402}
    295403
     
    429537}
    430538
     539#if ENABLE(NETWORK_CACHE)
     540void NetworkResourceLoader::didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
     541{
     542    if (isSynchronous()) {
     543        m_synchronousLoadData->response = entry->response;
     544        sendReplyToSynchronousRequest(*m_synchronousLoadData, entry->buffer.get());
     545    } else {
     546        sendAbortingOnFailure(Messages::WebResourceLoader::DidReceiveResponse(entry->response, m_parameters.isMainResource));
     547
     548        if (!entry->shareableResourceHandle.isNull())
     549            send(Messages::WebResourceLoader::DidReceiveResource(entry->shareableResourceHandle, currentTime()));
     550        else {
     551            bool shouldContinue = sendBufferMaybeAborting(*entry->buffer, entry->buffer->size());
     552            if (!shouldContinue)
     553                return;
     554            send(Messages::WebResourceLoader::DidFinishResourceLoad(currentTime()));
     555        }
     556    }
     557
     558    cleanup();
     559}
     560
     561void NetworkResourceLoader::validateCacheEntry(std::unique_ptr<NetworkCache::Entry> entry)
     562{
     563    ASSERT(!m_handle);
     564
     565    String eTag = entry->response.httpHeaderField(WebCore::HTTPHeaderName::ETag);
     566    String lastModified = entry->response.httpHeaderField(WebCore::HTTPHeaderName::LastModified);
     567    if (!eTag.isEmpty())
     568        m_currentRequest.setHTTPHeaderField(WebCore::HTTPHeaderName::IfNoneMatch, eTag);
     569    if (!lastModified.isEmpty())
     570        m_currentRequest.setHTTPHeaderField(WebCore::HTTPHeaderName::IfModifiedSince, lastModified);
     571
     572    m_cacheEntryForValidation = WTF::move(entry);
     573
     574    startNetworkLoad();
     575}
     576#endif
     577
    431578IPC::Connection* NetworkResourceLoader::messageSenderConnection()
    432579{
  • trunk/Source/WebKit2/NetworkProcess/NetworkResourceLoader.h

    r176858 r177294  
    3030
    3131#include "MessageSender.h"
     32#include "NetworkCache.h"
    3233#include "NetworkConnectionToWebProcessMessages.h"
    3334#include "NetworkResourceLoadParameters.h"
    3435#include "ShareableResource.h"
     36#include <WebCore/CacheValidation.h>
    3537#include <WebCore/ResourceError.h>
    3638#include <WebCore/ResourceHandleClient.h>
     
    99101#endif
    100102    void continueWillSendRequest(const WebCore::ResourceRequest& newRequest);
     103
     104    WebCore::SharedBuffer* bufferedData() { return m_bufferedData.get(); }
     105    const WebCore::ResourceResponse& response() const { return m_response; }
    101106
    102107    NetworkConnectionToWebProcess* connectionToWebProcess() const { return m_connection.get(); }
     
    143148#endif
    144149
     150#if ENABLE(NETWORK_CACHE)
     151    void didRetrieveCacheEntry(std::unique_ptr<NetworkCache::Entry>);
     152    void validateCacheEntry(std::unique_ptr<NetworkCache::Entry>);
     153#endif
     154
     155    void startNetworkLoad();
    145156    void continueDidReceiveResponse();
    146157
     
    168179
    169180    WebCore::ResourceRequest m_currentRequest;
     181    WebCore::ResourceResponse m_response;
    170182
    171183    size_t m_bytesReceived;
     
    181193
    182194    WebCore::Timer m_bufferingTimer;
     195#if ENABLE(NETWORK_CACHE)
     196    RefPtr<WebCore::SharedBuffer> m_bufferedDataForCache;
     197    std::unique_ptr<NetworkCache::Entry> m_cacheEntryForValidation;
     198
     199    WebCore::RedirectChainCacheStatus m_redirectChainCacheStatus;
     200#endif
    183201};
    184202
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheEncoder.cpp

    r176398 r177294  
    4242uint8_t* NetworkCacheEncoder::grow(size_t size)
    4343{
    44     uint8_t* position = m_buffer.data() + m_buffer.size();
     44    size_t newPosition = m_buffer.size();
    4545    m_buffer.grow(m_buffer.size() + size);
    46     return position;
     46    return m_buffer.data() + newPosition;
    4747}
    4848
  • trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm

    r177038 r177294  
    2929#if ENABLE(NETWORK_PROCESS)
    3030
     31#import "NetworkCache.h"
    3132#import "NetworkProcessCreationParameters.h"
    3233#import "NetworkResourceLoader.h"
     
    6364    if (!m_diskCacheDirectory.isNull()) {
    6465        SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
     66#if ENABLE(NETWORK_CACHE)
     67        if (NetworkCache::shared().initialize(m_diskCacheDirectory)) {
     68            NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil];
     69            [NSURLCache setSharedURLCache:URLCache];
     70            return;
     71        }
     72#endif
    6573#if PLATFORM(IOS)
    6674        [NSURLCache setSharedURLCache:adoptNS([[NSURLCache alloc]
     
    128136        pageCacheCapacity, urlCacheMemoryCapacity, urlCacheDiskCapacity);
    129137
     138#if ENABLE(NETWORK_CACHE)
     139    if (NetworkCache::shared().isEnabled()) {
     140        NetworkCache::shared().setMaximumSize(urlCacheDiskCapacity);
     141        return;
     142    }
     143#endif
    130144    NSURLCache *nsurlCache = [NSURLCache sharedURLCache];
    131145    [nsurlCache setMemoryCapacity:urlCacheMemoryCapacity];
     
    136150void NetworkProcess::clearDiskCache(std::chrono::system_clock::time_point modifiedSince, std::function<void ()> completionHandler)
    137151{
     152#if ENABLE(NETWORK_CACHE)
     153    NetworkCache::shared().clear();
     154#endif
     155
    138156    if (!m_clearCacheDispatchGroup)
    139157        m_clearCacheDispatchGroup = dispatch_group_create();
  • trunk/Source/WebKit2/NetworkProcess/ios/NetworkProcessIOS.mm

    r171066 r177294  
    2929#if PLATFORM(IOS) && ENABLE(NETWORK_PROCESS)
    3030
     31#import "NetworkCache.h"
    3132#import "NetworkProcessCreationParameters.h"
     33#import "ResourceCachesToClear.h"
    3234#import "SandboxInitializationParameters.h"
    3335#import "SecItemShim.h"
     
    7577}
    7678
    77 void NetworkProcess::clearCacheForAllOrigins(uint32_t)
     79void NetworkProcess::clearCacheForAllOrigins(uint32_t cachesToClear)
    7880{
     81    ResourceCachesToClear resourceCachesToClear = static_cast<ResourceCachesToClear>(cachesToClear);
     82    if (resourceCachesToClear == InMemoryResourceCachesOnly)
     83        return;
     84#if ENABLE(NETWORK_CACHE)
     85    NetworkCache::shared().clear();
     86#endif
    7987}
    8088
  • trunk/Source/WebKit2/NetworkProcess/mac/NetworkProcessMac.mm

    r177038 r177294  
    2929#if PLATFORM(MAC) && ENABLE(NETWORK_PROCESS)
    3030
     31#import "NetworkCache.h"
    3132#import "NetworkProcessCreationParameters.h"
    3233#import "NetworkResourceLoader.h"
  • trunk/Source/WebKit2/NetworkProcess/mac/NetworkResourceLoaderMac.mm

    r176448 r177294  
    4343static void tryGetShareableHandleFromCFData(ShareableResource::Handle& handle, CFDataRef data)
    4444{
    45     if (!data || CFDataGetLength(data) < (CFIndex)NetworkResourceLoader::fileBackedResourceMinimumSize())
    46         return;
    47 
    4845    RefPtr<SharedMemory> sharedMemory = SharedMemory::createFromVMBuffer((void*)CFDataGetBytePtr(data), CFDataGetLength(data));
    4946    if (!sharedMemory) {
  • trunk/Source/WebKit2/Platform/Logging.h

    r174524 r177294  
    5252    M(View) \
    5353    M(IDB) \
     54    M(NetworkCache) \
     55    M(NetworkCacheStorage) \
    5456
    5557#define DECLARE_LOG_CHANNEL(name) \
  • trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj

    r177192 r177294  
    16731673                E1EE53E311F8CFC000CCBEE4 /* InjectedBundlePageEditorClient.h in Headers */ = {isa = PBXBuildFile; fileRef = E1EE53DC11F8CF9F00CCBEE4 /* InjectedBundlePageEditorClient.h */; };
    16741674                E1EE53E711F8CFFB00CCBEE4 /* InjectedBundlePageEditorClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EE53E611F8CFFB00CCBEE4 /* InjectedBundlePageEditorClient.cpp */; };
     1675                E4436ECA1A0D03FA00EAD204 /* NetworkCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4436EBE1A0CFDB200EAD204 /* NetworkCache.cpp */; };
     1676                E4436ECC1A0D040B00EAD204 /* NetworkCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E4436EBF1A0CFDB200EAD204 /* NetworkCache.h */; };
     1677                E4436ECD1A0D040B00EAD204 /* NetworkCacheKey.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4436EC01A0CFDB200EAD204 /* NetworkCacheKey.cpp */; };
     1678                E4436ECE1A0D040B00EAD204 /* NetworkCacheKey.h in Headers */ = {isa = PBXBuildFile; fileRef = E4436EC11A0CFDB200EAD204 /* NetworkCacheKey.h */; };
     1679                E4436ECF1A0D040B00EAD204 /* NetworkCacheStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = E4436EC21A0CFDB200EAD204 /* NetworkCacheStorage.h */; };
     1680                E4436ED01A0D040B00EAD204 /* NetworkCacheStorageCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = E4436EC31A0CFDB200EAD204 /* NetworkCacheStorageCocoa.mm */; };
    16751681                E489D28A1A0A2DB80078C06A /* NetworkCacheCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = E489D2831A0A2DB80078C06A /* NetworkCacheCoder.h */; };
    16761682                E489D28B1A0A2DB80078C06A /* NetworkCacheCoders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E489D2841A0A2DB80078C06A /* NetworkCacheCoders.cpp */; };
     
    38033809                E1FEF39A190F76F300731658 /* com.apple.WebKit.Databases.sb.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = com.apple.WebKit.Databases.sb.in; sourceTree = "<group>"; };
    38043810                E1FEF39C190F791C00731658 /* DatabaseProcessIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DatabaseProcessIOS.mm; sourceTree = "<group>"; };
     3811                E4436EBE1A0CFDB200EAD204 /* NetworkCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCache.cpp; sourceTree = "<group>"; };
     3812                E4436EBF1A0CFDB200EAD204 /* NetworkCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCache.h; sourceTree = "<group>"; };
     3813                E4436EC01A0CFDB200EAD204 /* NetworkCacheKey.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCacheKey.cpp; sourceTree = "<group>"; };
     3814                E4436EC11A0CFDB200EAD204 /* NetworkCacheKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheKey.h; sourceTree = "<group>"; };
     3815                E4436EC21A0CFDB200EAD204 /* NetworkCacheStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheStorage.h; sourceTree = "<group>"; };
     3816                E4436EC31A0CFDB200EAD204 /* NetworkCacheStorageCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkCacheStorageCocoa.mm; sourceTree = "<group>"; };
    38053817                E489D2831A0A2DB80078C06A /* NetworkCacheCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheCoder.h; sourceTree = "<group>"; };
    38063818                E489D2841A0A2DB80078C06A /* NetworkCacheCoders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkCacheCoders.cpp; sourceTree = "<group>"; };
     
    71217133                        isa = PBXGroup;
    71227134                        children = (
     7135                                E4436EBE1A0CFDB200EAD204 /* NetworkCache.cpp */,
     7136                                E4436EBF1A0CFDB200EAD204 /* NetworkCache.h */,
    71237137                                E489D2831A0A2DB80078C06A /* NetworkCacheCoder.h */,
    71247138                                E489D2841A0A2DB80078C06A /* NetworkCacheCoders.cpp */,
     
    71287142                                E489D2881A0A2DB80078C06A /* NetworkCacheEncoder.cpp */,
    71297143                                E489D2891A0A2DB80078C06A /* NetworkCacheEncoder.h */,
     7144                                E4436EC01A0CFDB200EAD204 /* NetworkCacheKey.cpp */,
     7145                                E4436EC11A0CFDB200EAD204 /* NetworkCacheKey.h */,
     7146                                E4436EC21A0CFDB200EAD204 /* NetworkCacheStorage.h */,
     7147                                E4436EC31A0CFDB200EAD204 /* NetworkCacheStorageCocoa.mm */,
    71307148                        );
    71317149                        name = cache;
     
    72297247                                BCBAACF41452324F0053F82F /* WKBrowsingContextGroup.h in Headers */,
    72307248                                BCBAAD0B14560A430053F82F /* WKBrowsingContextLoadDelegate.h in Headers */,
     7249                                E4436ECE1A0D040B00EAD204 /* NetworkCacheKey.h in Headers */,
    72317250                                BCA284D71492F2C7001F9042 /* WKConnection.h in Headers */,
    72327251                                BC017D0716260FF4007054F5 /* WKDOMDocument.h in Headers */,
     
    76747693                                51A9E1061315CCFC009E7031 /* WebKeyValueStorageManager.h in Headers */,
    76757694                                373D122718A473F60066D9CC /* _WKFrameHandleInternal.h in Headers */,
     7695                                E4436ECF1A0D040B00EAD204 /* NetworkCacheStorage.h in Headers */,
    76767696                                1AE00D611831792100087DD7 /* FrameLoadState.h in Headers */,
    76777697                                BCB63478116BF10600603215 /* WebKit2_C.h in Headers */,
     
    78207840                                BC14DF9F120B635F00826C0C /* WKBundleScriptWorld.h in Headers */,
    78217841                                1AF4CEF018BC481800BC2D34 /* VisitedLinkTableController.h in Headers */,
     7842                                E4436ECC1A0D040B00EAD204 /* NetworkCache.h in Headers */,
    78227843                                BC4075F6124FF0270068F20A /* WKCertificateInfo.h in Headers */,
    78237844                                BC407627124FF0400068F20A /* WKCertificateInfoMac.h in Headers */,
     
    90659086                                1A6280F31919982A006AD9F9 /* WebKit.m in Sources */,
    90669087                                51FD18B51651FBAD00DBE1CE /* NetworkResourceLoader.cpp in Sources */,
     9088                                E4436ECD1A0D040B00EAD204 /* NetworkCacheKey.cpp in Sources */,
    90679089                                51E3B67F16F266B3009968DC /* NetworkResourceLoaderMac.mm in Sources */,
    90689090                                E152551A17011819003D7ADB /* NetworkResourceLoaderMessageReceiver.cpp in Sources */,
     
    94269448                                9321D5881A38EE74008052BE /* WKImmediateActionController.mm in Sources */,
    94279449                                1A002D48196B345D00B9AD44 /* SessionStateCoding.mm in Sources */,
     9450                                E4436ED01A0D040B00EAD204 /* NetworkCacheStorageCocoa.mm in Sources */,
    94289451                                BC306825125A6B9400E71278 /* WebProcessCreationParameters.cpp in Sources */,
    94299452                                1F7506B01859162C00EC0FF7 /* WKWebProcessPlugInScriptWorld.mm in Sources */,
     
    94569479                                0F5947A7187B517600437857 /* RemoteScrollingCoordinatorMessageReceiver.cpp in Sources */,
    94579480                                D3B9484811FF4B6500032B39 /* WebSearchPopupMenu.cpp in Sources */,
     9481                                E4436ECA1A0D03FA00EAD204 /* NetworkCache.cpp in Sources */,
    94589482                                BCC5715C115ADAEF001CCAF9 /* WebSystemInterface.mm in Sources */,
    94599483                                C0337DD8127A51B6008FF4F4 /* WebTouchEvent.cpp in Sources */,
  • trunk/Source/WebKit2/config.h

    r173393 r177294  
    9393#endif
    9494#endif
     95
     96#ifndef ENABLE_NETWORK_CACHE
     97#if PLATFORM(MAC) && ENABLE(NETWORK_PROCESS)
     98#define ENABLE_NETWORK_CACHE 0
     99#endif
     100#endif
Note: See TracChangeset for help on using the changeset viewer.