Changeset 229560 in webkit


Ignore:
Timestamp:
Mar 12, 2018 4:06:51 PM (6 years ago)
Author:
Chris Dumez
Message:

Load may get committed before receiving policy for the resource response
https://bugs.webkit.org/show_bug.cgi?id=183579
<rdar://problem/38268780>

Reviewed by Youenn Fablet.

Source/WebKit:

r228852 updated WebResourceLoader::didReceiveResponse to only send the
ContinueDidReceiveResponse IPC back to the Networkprocess *after* the
policy decision for the resource response has been made. This is necessary
now that policy decisions can be made asynchronously.

However, one of the 2 code paths in NetworkProcess side (code path when
the resource is already in the HTTP disk cache) failed to wait for the
ContinueDidReceiveResponse IPC before sending over the data to the WebProcess.
As a result, the WebProcess could commit the load before even receiving the
policy response from the client.

  • NetworkProcess/NetworkResourceLoader.cpp:

(WebKit::NetworkResourceLoader::continueDidReceiveResponse):
(WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
(WebKit::NetworkResourceLoader::continueProcessingCachedEntryAfterDidReceiveResponse):

  • NetworkProcess/NetworkResourceLoader.h:

Make sure NetworkResourceLoader::didRetrieveCacheEntry() does not start sending the data
until the network process gets the ContinueDidReceiveResponse IPC back from the WebProcess.

  • WebProcess/Network/WebResourceLoader.cpp:

(WebKit::WebResourceLoader::didReceiveResponse):
(WebKit::WebResourceLoader::didReceiveData):

  • WebProcess/Network/WebResourceLoader.h:

Add assertion to make sure didReceiveData() never gets called before didReceiveResponse's
completion handler has been called. If this hits, then the load may get committed even
though the client did not reply to the policy for the resource response yet.

LayoutTests:

Add layout test coverage.

  • http/tests/cache/cachedEntry-waits-for-response-policy-expected.txt: Added.
  • http/tests/cache/cachedEntry-waits-for-response-policy.html: Added.
Location:
trunk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r229558 r229560  
     12018-03-12  Chris Dumez  <cdumez@apple.com>
     2
     3        Load may get committed before receiving policy for the resource response
     4        https://bugs.webkit.org/show_bug.cgi?id=183579
     5        <rdar://problem/38268780>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        Add layout test coverage.
     10
     11        * http/tests/cache/cachedEntry-waits-for-response-policy-expected.txt: Added.
     12        * http/tests/cache/cachedEntry-waits-for-response-policy.html: Added.
     13
    1142018-03-12  Ali Juma  <ajuma@chromium.org>
    215
  • trunk/Source/WebKit/ChangeLog

    r229558 r229560  
     12018-03-12  Chris Dumez  <cdumez@apple.com>
     2
     3        Load may get committed before receiving policy for the resource response
     4        https://bugs.webkit.org/show_bug.cgi?id=183579
     5        <rdar://problem/38268780>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        r228852 updated WebResourceLoader::didReceiveResponse to only send the
     10        ContinueDidReceiveResponse IPC back to the Networkprocess *after* the
     11        policy decision for the resource response has been made. This is necessary
     12        now that policy decisions can be made asynchronously.
     13
     14        However, one of the 2 code paths in NetworkProcess side (code path when
     15        the resource is already in the HTTP disk cache) failed to wait for the
     16        ContinueDidReceiveResponse IPC before sending over the data to the WebProcess.
     17        As a result, the WebProcess could commit the load before even receiving the
     18        policy response from the client.       
     19
     20        * NetworkProcess/NetworkResourceLoader.cpp:
     21        (WebKit::NetworkResourceLoader::continueDidReceiveResponse):
     22        (WebKit::NetworkResourceLoader::didRetrieveCacheEntry):
     23        (WebKit::NetworkResourceLoader::continueProcessingCachedEntryAfterDidReceiveResponse):
     24        * NetworkProcess/NetworkResourceLoader.h:
     25        Make sure NetworkResourceLoader::didRetrieveCacheEntry() does not start sending the data
     26        until the network process gets the ContinueDidReceiveResponse IPC back from the WebProcess.
     27
     28        * WebProcess/Network/WebResourceLoader.cpp:
     29        (WebKit::WebResourceLoader::didReceiveResponse):
     30        (WebKit::WebResourceLoader::didReceiveData):
     31        * WebProcess/Network/WebResourceLoader.h:
     32        Add assertion to make sure didReceiveData() never gets called before didReceiveResponse's
     33        completion handler has been called. If this hits, then the load may get committed even
     34        though the client did not reply to the policy for the resource response yet.
     35
    1362018-03-12  Ali Juma  <ajuma@chromium.org>
    237
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

    r229209 r229560  
    489489void NetworkResourceLoader::continueDidReceiveResponse()
    490490{
     491    if (m_cacheEntryWaitingForContinueDidReceiveResponse) {
     492        continueProcessingCachedEntryAfterDidReceiveResponse(WTFMove(m_cacheEntryWaitingForContinueDidReceiveResponse));
     493        return;
     494    }
     495
    491496    // FIXME: Remove this check once BlobResourceHandle implements didReceiveResponseAsync correctly.
    492497    // Currently, it does not wait for response, so the load is likely to finish before continueDidReceiveResponse.
     
    564569    send(Messages::WebResourceLoader::DidReceiveResponse(entry->response(), needsContinueDidReceiveResponseMessage));
    565570
     571    if (needsContinueDidReceiveResponseMessage)
     572        m_cacheEntryWaitingForContinueDidReceiveResponse = WTFMove(entry);
     573    else
     574        continueProcessingCachedEntryAfterDidReceiveResponse(WTFMove(entry));
     575}
     576
     577void NetworkResourceLoader::continueProcessingCachedEntryAfterDidReceiveResponse(std::unique_ptr<NetworkCache::Entry> entry)
     578{
    566579    if (entry->sourceStorageRecord().bodyHash && !m_parameters.derivedCachedDataTypesToRetrieve.isEmpty()) {
    567580        auto bodyHash = *entry->sourceStorageRecord().bodyHash;
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.h

    r228231 r229560  
    127127    void validateCacheEntry(std::unique_ptr<NetworkCache::Entry>);
    128128    void dispatchWillSendRequestForCacheEntry(std::unique_ptr<NetworkCache::Entry>);
     129    void continueProcessingCachedEntryAfterDidReceiveResponse(std::unique_ptr<NetworkCache::Entry>);
    129130
    130131    void startNetworkLoad(const WebCore::ResourceRequest&);
     
    175176    std::unique_ptr<NetworkCache::Entry> m_cacheEntryForValidation;
    176177    bool m_isWaitingContinueWillSendRequestForCachedRedirect { false };
     178    std::unique_ptr<NetworkCache::Entry> m_cacheEntryWaitingForContinueDidReceiveResponse;
    177179};
    178180
  • trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp

    r228852 r229560  
    115115    CompletionHandler<void()> policyDecisionCompletionHandler;
    116116    if (needsContinueDidReceiveResponseMessage) {
     117#if !ASSERT_DISABLED
     118        m_isProcessingNetworkResponse = true;
     119#endif
    117120        policyDecisionCompletionHandler = [this, protectedThis = WTFMove(protectedThis)] {
     121#if !ASSERT_DISABLED
     122            m_isProcessingNetworkResponse = false;
     123#endif
    118124            // If m_coreLoader becomes null as a result of the didReceiveResponse callback, we can't use the send function().
    119125            if (m_coreLoader)
     
    128134{
    129135    LOG(Network, "(WebProcess) WebResourceLoader::didReceiveData of size %lu for '%s'", data.size(), m_coreLoader->url().string().latin1().data());
     136    ASSERT_WITH_MESSAGE(!m_isProcessingNetworkResponse, "Network process should not send data until we've validated the response");
    130137
    131138    if (!m_numBytesReceived) {
     
    150157    RELEASE_LOG_IF_ALLOWED("didFinishResourceLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", length = %zd)", m_trackingParameters.pageID, m_trackingParameters.frameID, m_trackingParameters.resourceID, m_numBytesReceived);
    151158
     159    ASSERT_WITH_MESSAGE(!m_isProcessingNetworkResponse, "Load should not be able to finish before we've validated the response");
    152160    m_coreLoader->didFinishLoading(networkLoadMetrics);
    153161}
     
    157165    LOG(Network, "(WebProcess) WebResourceLoader::didFailResourceLoad for '%s'", m_coreLoader->url().string().latin1().data());
    158166    RELEASE_LOG_IF_ALLOWED("didFailResourceLoad: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ")", m_trackingParameters.pageID, m_trackingParameters.frameID, m_trackingParameters.resourceID);
     167
     168    ASSERT_WITH_MESSAGE(!m_isProcessingNetworkResponse, "Load should not be able to finish before we've validated the response");
    159169
    160170    if (m_coreLoader->documentLoader()->applicationCacheHost().maybeLoadFallbackForError(m_coreLoader.get(), error))
  • trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.h

    r228231 r229560  
    9090    TrackingParameters m_trackingParameters;
    9191    size_t m_numBytesReceived { 0 };
     92
     93#if !ASSERT_DISABLED
     94    bool m_isProcessingNetworkResponse { false };
     95#endif
    9296};
    9397
Note: See TracChangeset for help on using the changeset viewer.