Changeset 228852 in webkit


Ignore:
Timestamp:
Feb 20, 2018 5:08:28 PM (6 years ago)
Author:
Chris Dumez
Message:

Provisional load may get committed before receiving the decidePolicyForNavigationResponse response
https://bugs.webkit.org/show_bug.cgi?id=182720
<rdar://problem/37515204>

Reviewed by Alex Christensen.

Source/WebCore:

Wait for the policy response from the client after receiving a resource response,
before sending the NetworkResourceLoader::ContinueDidReceiveResponse IPC back to
the NetworkProcess. Otherwise, the network process may start sending us data and
we may end up committing the provisional load before receiving the policy decision
fron the client.

Change is covered by new API test.

  • loader/DocumentLoader.cpp:

(WebCore::DocumentLoader::responseReceived):

  • loader/NetscapePlugInStreamLoader.cpp:

(WebCore::NetscapePlugInStreamLoader::didReceiveResponse):

  • loader/NetscapePlugInStreamLoader.h:
  • loader/ResourceLoader.cpp:

(WebCore::ResourceLoader::deliverResponseAndData):
(WebCore::ResourceLoader::loadDataURL):
(WebCore::ResourceLoader::didReceiveResponse):
(WebCore::ResourceLoader::didReceiveResponseAsync):

  • loader/ResourceLoader.h:
  • loader/SubresourceLoader.cpp:

(WebCore::SubresourceLoader::didReceiveResponse):
(WebCore::SubresourceLoader::didReceiveResponsePolicy):
(WebCore::SubresourceLoader::willCancel):

  • loader/SubresourceLoader.h:
  • loader/ios/PreviewLoader.mm:

(-[WebPreviewLoader _sendDidReceiveResponseIfNecessary]):

Source/WebKit:

  • WebProcess/Network/WebResourceLoader.cpp:

(WebKit::WebResourceLoader::didReceiveResponse):

  • WebProcess/Storage/ServiceWorkerClientFetch.cpp:

(WebKit::ServiceWorkerClientFetch::didReceiveResponse):

  • WebProcess/WebPage/WebURLSchemeTaskProxy.cpp:

(WebKit::WebURLSchemeTaskProxy::didReceiveResponse):

Source/WTF:

Add convenience CompletionHandlerCallingScope class which calls its CompletionHandler
when destroyed, and provides a release() methods to manually call the completionHandler.

  • wtf/CompletionHandler.h:

(WTF::CompletionHandlerCallingScope::CompletionHandlerCallingScope):
(WTF::CompletionHandlerCallingScope::~CompletionHandlerCallingScope):
(WTF::CompletionHandlerCallingScope::CompletionHandler<void):

Tools:

Add API test coverage.

  • TestWebKitAPI/Tests/WebKitCocoa/AsyncPolicyForNavigationResponse.mm:

(-[TestAsyncNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
(TestWebKitAPI::TEST):

Location:
trunk
Files:
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r228846 r228852  
     12018-02-20  Chris Dumez  <cdumez@apple.com>
     2
     3        Provisional load may get committed before receiving the decidePolicyForNavigationResponse response
     4        https://bugs.webkit.org/show_bug.cgi?id=182720
     5        <rdar://problem/37515204>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Add convenience CompletionHandlerCallingScope class which calls its CompletionHandler
     10        when destroyed, and provides a release() methods to manually call the completionHandler.
     11
     12        * wtf/CompletionHandler.h:
     13        (WTF::CompletionHandlerCallingScope::CompletionHandlerCallingScope):
     14        (WTF::CompletionHandlerCallingScope::~CompletionHandlerCallingScope):
     15        (WTF::CompletionHandlerCallingScope::CompletionHandler<void):
     16
    1172018-02-20  Tim Horton  <timothy_horton@apple.com>
    218
  • trunk/Source/WTF/wtf/CompletionHandler.h

    r225403 r228852  
    6565};
    6666
     67class CompletionHandlerCallingScope {
     68public:
     69    CompletionHandlerCallingScope(CompletionHandler<void()>&& completionHandler)
     70        : m_completionHandler(WTFMove(completionHandler))
     71    { }
     72
     73    ~CompletionHandlerCallingScope()
     74    {
     75        if (m_completionHandler)
     76            m_completionHandler();
     77    }
     78
     79    CompletionHandlerCallingScope(CompletionHandlerCallingScope&&) = default;
     80    CompletionHandlerCallingScope& operator=(CompletionHandlerCallingScope&&) = default;
     81
     82    CompletionHandler<void()> release() { return WTFMove(m_completionHandler); }
     83
     84private:
     85    CompletionHandler<void()> m_completionHandler;
     86};
     87
    6788} // namespace WTF
    6889
    6990using WTF::CompletionHandler;
     91using WTF::CompletionHandlerCallingScope;
  • trunk/Source/WebCore/ChangeLog

    r228851 r228852  
     12018-02-20  Chris Dumez  <cdumez@apple.com>
     2
     3        Provisional load may get committed before receiving the decidePolicyForNavigationResponse response
     4        https://bugs.webkit.org/show_bug.cgi?id=182720
     5        <rdar://problem/37515204>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Wait for the policy response from the client after receiving a resource response,
     10        before sending the NetworkResourceLoader::ContinueDidReceiveResponse IPC back to
     11        the NetworkProcess. Otherwise, the network process may start sending us data and
     12        we may end up committing the provisional load before receiving the policy decision
     13        fron the client.
     14
     15        Change is covered by new API test.
     16
     17        * loader/DocumentLoader.cpp:
     18        (WebCore::DocumentLoader::responseReceived):
     19        * loader/NetscapePlugInStreamLoader.cpp:
     20        (WebCore::NetscapePlugInStreamLoader::didReceiveResponse):
     21        * loader/NetscapePlugInStreamLoader.h:
     22        * loader/ResourceLoader.cpp:
     23        (WebCore::ResourceLoader::deliverResponseAndData):
     24        (WebCore::ResourceLoader::loadDataURL):
     25        (WebCore::ResourceLoader::didReceiveResponse):
     26        (WebCore::ResourceLoader::didReceiveResponseAsync):
     27        * loader/ResourceLoader.h:
     28        * loader/SubresourceLoader.cpp:
     29        (WebCore::SubresourceLoader::didReceiveResponse):
     30        (WebCore::SubresourceLoader::didReceiveResponsePolicy):
     31        (WebCore::SubresourceLoader::willCancel):
     32        * loader/SubresourceLoader.h:
     33        * loader/ios/PreviewLoader.mm:
     34        (-[WebPreviewLoader _sendDidReceiveResponseIfNecessary]):
     35
    1362018-02-20  Chris Dumez  <cdumez@apple.com>
    237
  • trunk/Source/WebCore/loader/DocumentLoader.cpp

    r228691 r228852  
    784784#endif
    785785
     786    if (auto* mainResourceLoader = this->mainResourceLoader())
     787        mainResourceLoader->markInAsyncResponsePolicyCheck();
    786788    frameLoader()->checkContentPolicy(m_response, [this, protectedThis = makeRef(*this)](PolicyAction policy) {
     789        if (auto* mainResourceLoader = this->mainResourceLoader())
     790            mainResourceLoader->didReceiveResponsePolicy();
     791
    787792        continueAfterContentPolicy(policy);
    788793    });
  • trunk/Source/WebCore/loader/NetscapePlugInStreamLoader.cpp

    r224522 r228852  
    9898}
    9999
    100 void NetscapePlugInStreamLoader::didReceiveResponse(const ResourceResponse& response)
     100void NetscapePlugInStreamLoader::didReceiveResponse(const ResourceResponse& response, CompletionHandler<void()>&& policyCompletionHandler)
    101101{
    102102    Ref<NetscapePlugInStreamLoader> protectedThis(*this);
     103    CompletionHandlerCallingScope completionHandlerCaller(WTFMove(policyCompletionHandler));
    103104
    104105    m_client->didReceiveResponse(this, response);
     
    108109        return;
    109110
    110     ResourceLoader::didReceiveResponse(response);
     111    ResourceLoader::didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis), response, completionHandlerCaller = WTFMove(completionHandlerCaller)]() mutable {
     112        // Don't continue if the stream is cancelled
     113        if (!m_client)
     114            return;
    111115
    112     // Don't continue if the stream is cancelled
    113     if (!m_client)
    114         return;
     116        if (!response.isHTTP())
     117            return;
    115118
    116     if (!response.isHTTP())
    117         return;
    118    
    119     if (m_client->wantsAllStreams())
    120         return;
     119        if (m_client->wantsAllStreams())
     120            return;
    121121
    122     // Status code can be null when serving from a Web archive.
    123     if (response.httpStatusCode() && (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400))
    124         cancel(frameLoader()->client().fileDoesNotExistError(response));
     122        // Status code can be null when serving from a Web archive.
     123        if (response.httpStatusCode() && (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400))
     124            cancel(frameLoader()->client().fileDoesNotExistError(response));
     125    });
    125126}
    126127
  • trunk/Source/WebCore/loader/NetscapePlugInStreamLoader.h

    r224522 r228852  
    6161
    6262    void willSendRequest(ResourceRequest&&, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& callback) override;
    63     void didReceiveResponse(const ResourceResponse&) override;
     63    void didReceiveResponse(const ResourceResponse&, CompletionHandler<void()>&& policyCompletionHandler) override;
    6464    void didReceiveData(const char*, unsigned, long long encodedDataLength, DataPayloadType) override;
    6565    void didReceiveBuffer(Ref<SharedBuffer>&&, long long encodedDataLength, DataPayloadType) override;
  • trunk/Source/WebCore/loader/ResourceLoader.cpp

    r228703 r228852  
    170170void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, RefPtr<SharedBuffer>&& buffer)
    171171{
    172     Ref<ResourceLoader> protectedThis(*this);
    173 
    174     didReceiveResponse(response);
    175     if (reachedTerminalState())
    176         return;
    177 
    178     if (buffer) {
    179         unsigned size = buffer->size();
    180         didReceiveBuffer(buffer.releaseNonNull(), size, DataPayloadWholeResource);
     172    didReceiveResponse(response, [this, protectedThis = makeRef(*this), buffer = WTFMove(buffer)]() mutable {
    181173        if (reachedTerminalState())
    182174            return;
    183     }
    184 
    185     NetworkLoadMetrics emptyMetrics;
    186     didFinishLoading(emptyMetrics);
     175
     176        if (buffer) {
     177            unsigned size = buffer->size();
     178            didReceiveBuffer(buffer.releaseNonNull(), size, DataPayloadWholeResource);
     179            if (reachedTerminalState())
     180                return;
     181        }
     182
     183        NetworkLoadMetrics emptyMetrics;
     184        didFinishLoading(emptyMetrics);
     185    });
    187186}
    188187
     
    252251        scheduleContext.scheduledPairs = *scheduledPairs;
    253252#endif
    254     DataURLDecoder::decode(url, scheduleContext, [protectedThis = makeRef(*this), url](auto decodeResult) {
    255         if (protectedThis->reachedTerminalState())
     253    DataURLDecoder::decode(url, scheduleContext, [this, protectedThis = makeRef(*this), url](auto decodeResult) mutable {
     254        if (this->reachedTerminalState())
    256255            return;
    257256        if (!decodeResult) {
     
    259258            return;
    260259        }
    261         if (protectedThis->wasCancelled())
     260        if (this->wasCancelled())
    262261            return;
    263262        auto& result = decodeResult.value();
     
    269268        dataResponse.setHTTPHeaderField(HTTPHeaderName::ContentType, result.contentType);
    270269        dataResponse.setSource(ResourceResponse::Source::Network);
    271         protectedThis->didReceiveResponse(dataResponse);
    272 
    273         if (!protectedThis->reachedTerminalState() && dataSize)
    274             protectedThis->didReceiveBuffer(result.data.releaseNonNull(), dataSize, DataPayloadWholeResource);
    275 
    276         if (!protectedThis->reachedTerminalState()) {
    277             NetworkLoadMetrics emptyMetrics;
    278             protectedThis->didFinishLoading(emptyMetrics);
    279         }
     270        this->didReceiveResponse(dataResponse, [this, protectedThis = WTFMove(protectedThis), dataSize, data = result.data.releaseNonNull()]() mutable {
     271            if (!this->reachedTerminalState() && dataSize)
     272                this->didReceiveBuffer(WTFMove(data), dataSize, DataPayloadWholeResource);
     273
     274            if (!this->reachedTerminalState()) {
     275                NetworkLoadMetrics emptyMetrics;
     276                this->didFinishLoading(emptyMetrics);
     277            }
     278        });
    280279    });
    281280}
     
    460459}
    461460
    462 void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
     461void ResourceLoader::didReceiveResponse(const ResourceResponse& r, CompletionHandler<void()>&& policyCompletionHandler)
    463462{
    464463    ASSERT(!m_reachedTerminalState);
     464    CompletionHandlerCallingScope completionHandlerCaller(WTFMove(policyCompletionHandler));
    465465
    466466    // Protect this in this delegate method since the additional processing can do
     
    661661        return;
    662662    }
    663     didReceiveResponse(response);
    664     completionHandler();
     663    didReceiveResponse(response, WTFMove(completionHandler));
    665664}
    666665
  • trunk/Source/WebCore/loader/ResourceLoader.h

    r228703 r228852  
    102102    virtual void willSendRequest(ResourceRequest&&, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&& callback);
    103103    virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
    104     virtual void didReceiveResponse(const ResourceResponse&);
     104    virtual void didReceiveResponse(const ResourceResponse&, CompletionHandler<void()>&& policyCompletionHandler);
    105105    virtual void didReceiveData(const char*, unsigned, long long encodedDataLength, DataPayloadType);
    106106    virtual void didReceiveBuffer(Ref<SharedBuffer>&&, long long encodedDataLength, DataPayloadType);
  • trunk/Source/WebCore/loader/SubresourceLoader.cpp

    r228486 r228852  
    289289#endif
    290290
    291 void SubresourceLoader::didReceiveResponse(const ResourceResponse& response)
     291void SubresourceLoader::didReceiveResponse(const ResourceResponse& response, CompletionHandler<void()>&& policyCompletionHandler)
    292292{
    293293    ASSERT(!response.isNull());
    294294    ASSERT(m_state == Initialized);
     295
     296    CompletionHandlerCallingScope completionHandlerCaller(WTFMove(policyCompletionHandler));
    295297
    296298#if USE(QUICK_LOOK)
     
    336338                m_frame->page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::cachedResourceRevalidationKey(), emptyString(), DiagnosticLoggingResultPass, ShouldSample::Yes);
    337339            if (!reachedTerminalState())
    338                 ResourceLoader::didReceiveResponse(revalidationResponse);
     340                ResourceLoader::didReceiveResponse(revalidationResponse, [completionHandlerCaller = WTFMove(completionHandlerCaller)] { });
    339341            return;
    340342        }
     
    357359        return;
    358360
    359     ResourceLoader::didReceiveResponse(response);
    360     if (reachedTerminalState())
    361         return;
    362 
    363     // FIXME: Main resources have a different set of rules for multipart than images do.
    364     // Hopefully we can merge those 2 paths.
    365     if (response.isMultipart() && m_resource->type() != CachedResource::MainResource) {
    366         m_loadingMultipartContent = true;
    367 
    368         // We don't count multiParts in a CachedResourceLoader's request count
    369         m_requestCountTracker = std::nullopt;
    370         if (!m_resource->isImage()) {
    371             cancel();
     361    bool isResponseMultipart = response.isMultipart();
     362    ResourceLoader::didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis), isResponseMultipart, completionHandlerCaller = WTFMove(completionHandlerCaller)]() mutable {
     363        if (reachedTerminalState())
    372364            return;
    373         }
    374     }
    375 
    376     auto* buffer = resourceData();
    377     if (m_loadingMultipartContent && buffer && buffer->size()) {
    378         // The resource data will change as the next part is loaded, so we need to make a copy.
    379         m_resource->finishLoading(buffer->copy().ptr());
    380         clearResourceData();
    381         // Since a subresource loader does not load multipart sections progressively, data was delivered to the loader all at once.
    382         // After the first multipart section is complete, signal to delegates that this load is "finished"
    383         NetworkLoadMetrics emptyMetrics;
    384         m_documentLoader->subresourceLoaderFinishedLoadingOnePart(this);
    385         didFinishLoadingOnePart(emptyMetrics);
    386     }
    387 
    388     checkForHTTPStatusCodeError();
     365
     366        // FIXME: Main resources have a different set of rules for multipart than images do.
     367        // Hopefully we can merge those 2 paths.
     368        if (isResponseMultipart && m_resource->type() != CachedResource::MainResource) {
     369            m_loadingMultipartContent = true;
     370
     371            // We don't count multiParts in a CachedResourceLoader's request count
     372            m_requestCountTracker = std::nullopt;
     373            if (!m_resource->isImage()) {
     374                cancel();
     375                return;
     376            }
     377        }
     378
     379        auto* buffer = resourceData();
     380        if (m_loadingMultipartContent && buffer && buffer->size()) {
     381            // The resource data will change as the next part is loaded, so we need to make a copy.
     382            m_resource->finishLoading(buffer->copy().ptr());
     383            clearResourceData();
     384            // Since a subresource loader does not load multipart sections progressively, data was delivered to the loader all at once.
     385            // After the first multipart section is complete, signal to delegates that this load is "finished"
     386            NetworkLoadMetrics emptyMetrics;
     387            m_documentLoader->subresourceLoaderFinishedLoadingOnePart(this);
     388            didFinishLoadingOnePart(emptyMetrics);
     389        }
     390
     391        checkForHTTPStatusCodeError();
     392
     393        if (m_inAsyncResponsePolicyCheck)
     394            m_policyForResponseCompletionHandler = completionHandlerCaller.release();
     395    });
     396}
     397
     398void SubresourceLoader::didReceiveResponsePolicy()
     399{
     400    ASSERT(m_inAsyncResponsePolicyCheck);
     401    m_inAsyncResponsePolicyCheck = false;
     402    if (auto completionHandler = WTFMove(m_policyForResponseCompletionHandler))
     403        completionHandler();
    389404}
    390405
     
    660675    LOG(ResourceLoading, "Cancelled load of '%s'.\n", m_resource->url().string().latin1().data());
    661676
     677    if (auto policyForResponseCompletionHandler = WTFMove(m_policyForResponseCompletionHandler))
     678        policyForResponseCompletionHandler();
     679
    662680    Ref<SubresourceLoader> protectedThis(*this);
    663681#if PLATFORM(IOS)
  • trunk/Source/WebCore/loader/SubresourceLoader.h

    r228486 r228852  
    3131#include "FrameLoaderTypes.h"
    3232#include "ResourceLoader.h"
     33#include <wtf/CompletionHandler.h>
    3334#include <wtf/text/WTFString.h>
    3435 
     
    6162    unsigned redirectCount() const { return m_redirectCount; }
    6263
     64    void markInAsyncResponsePolicyCheck() { m_inAsyncResponsePolicyCheck = true; }
     65    void didReceiveResponsePolicy();
     66
    6367private:
    6468    SubresourceLoader(Frame&, CachedResource&, const ResourceLoaderOptions&);
     
    6872    void willSendRequestInternal(ResourceRequest&&, const ResourceResponse& redirectResponse, CompletionHandler<void(ResourceRequest&&)>&&) override;
    6973    void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) override;
    70     void didReceiveResponse(const ResourceResponse&) override;
     74    void didReceiveResponse(const ResourceResponse&, CompletionHandler<void()>&& policyCompletionHandler) override;
    7175    void didReceiveData(const char*, unsigned, long long encodedDataLength, DataPayloadType) override;
    7276    void didReceiveBuffer(Ref<SharedBuffer>&&, long long encodedDataLength, DataPayloadType) override;
     
    125129    std::optional<RequestCountTracker> m_requestCountTracker;
    126130    RefPtr<SecurityOrigin> m_origin;
     131    CompletionHandler<void()> m_policyForResponseCompletionHandler;
    127132    unsigned m_redirectCount { 0 };
    128133    bool m_loadingMultipartContent { false };
     134    bool m_inAsyncResponsePolicyCheck { false };
    129135};
    130136
  • trunk/Source/WebCore/loader/ios/PreviewLoader.mm

    r220809 r228852  
    131131
    132132    _hasSentDidReceiveResponse = YES;
    133     _resourceLoader->didReceiveResponse(response);
     133    _resourceLoader->didReceiveResponse(response, nullptr);
    134134}
    135135
  • trunk/Source/WebKit/ChangeLog

    r228845 r228852  
     12018-02-20  Chris Dumez  <cdumez@apple.com>
     2
     3        Provisional load may get committed before receiving the decidePolicyForNavigationResponse response
     4        https://bugs.webkit.org/show_bug.cgi?id=182720
     5        <rdar://problem/37515204>
     6
     7        Reviewed by Alex Christensen.
     8
     9        * WebProcess/Network/WebResourceLoader.cpp:
     10        (WebKit::WebResourceLoader::didReceiveResponse):
     11        * WebProcess/Storage/ServiceWorkerClientFetch.cpp:
     12        (WebKit::ServiceWorkerClientFetch::didReceiveResponse):
     13        * WebProcess/WebPage/WebURLSchemeTaskProxy.cpp:
     14        (WebKit::WebURLSchemeTaskProxy::didReceiveResponse):
     15
    1162018-02-20  Matt Lewis  <jlewis3@apple.com>
    217
  • trunk/Source/WebKit/WebProcess/Network/WebResourceLoader.cpp

    r228231 r228852  
    108108    RELEASE_LOG_IF_ALLOWED("didReceiveResponse: (pageID = %" PRIu64 ", frameID = %" PRIu64 ", resourceID = %" PRIu64 ", status = %d)", m_trackingParameters.pageID, m_trackingParameters.frameID, m_trackingParameters.resourceID, response.httpStatusCode());
    109109
    110     Ref<WebResourceLoader> protect(*this);
     110    Ref<WebResourceLoader> protectedThis(*this);
    111111
    112112    if (m_coreLoader->documentLoader()->applicationCacheHost().maybeLoadFallbackForResponse(m_coreLoader.get(), response))
    113113        return;
    114114
    115     m_coreLoader->didReceiveResponse(response);
    116 
    117     // If m_coreLoader becomes null as a result of the didReceiveResponse callback, we can't use the send function().
    118     if (!m_coreLoader)
    119         return;
    120 
    121     if (needsContinueDidReceiveResponseMessage)
    122         send(Messages::NetworkResourceLoader::ContinueDidReceiveResponse());
     115    CompletionHandler<void()> policyDecisionCompletionHandler;
     116    if (needsContinueDidReceiveResponseMessage) {
     117        policyDecisionCompletionHandler = [this, protectedThis = WTFMove(protectedThis)] {
     118            // If m_coreLoader becomes null as a result of the didReceiveResponse callback, we can't use the send function().
     119            if (m_coreLoader)
     120                send(Messages::NetworkResourceLoader::ContinueDidReceiveResponse());
     121        };
     122    }
     123
     124    m_coreLoader->didReceiveResponse(response, WTFMove(policyDecisionCompletionHandler));
    123125}
    124126
  • trunk/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp

    r228198 r228852  
    142142            response.setURL(m_loader->request().url());
    143143
    144         m_loader->didReceiveResponse(response);
    145         if (auto callback = WTFMove(m_callback))
    146             callback(Result::Succeeded);
     144        m_loader->didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis)] {
     145            if (auto callback = WTFMove(m_callback))
     146                callback(Result::Succeeded);
     147        });
    147148    });
    148149}
  • trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp

    r225358 r228852  
    9494        return;
    9595
    96     m_coreLoader->didReceiveResponse(response);
     96    m_coreLoader->didReceiveResponse(response, nullptr);
    9797}
    9898
  • trunk/Tools/ChangeLog

    r228827 r228852  
     12018-02-20  Chris Dumez  <cdumez@apple.com>
     2
     3        Provisional load may get committed before receiving the decidePolicyForNavigationResponse response
     4        https://bugs.webkit.org/show_bug.cgi?id=182720
     5        <rdar://problem/37515204>
     6
     7        Reviewed by Alex Christensen.
     8
     9        Add API test coverage.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/AsyncPolicyForNavigationResponse.mm:
     12        (-[TestAsyncNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
     13        (TestWebKitAPI::TEST):
     14
    1152018-02-20  Nan Wang  <n_wang@apple.com>
    216
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncPolicyForNavigationResponse.mm

    r228430 r228852  
    3232
    3333#if WK_API_ENABLED
     34static bool shouldAccept = true;
    3435static bool navigationComplete = false;
    3536static bool navigationFailed = false;
     
    6768    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, deferredWaitTime);
    6869    dispatch_after(when, dispatch_get_main_queue(), ^{
    69         decisionHandler(WKNavigationResponsePolicyAllow);
     70        decisionHandler(shouldAccept ? WKNavigationResponsePolicyAllow : WKNavigationResponsePolicyCancel);
    7071    });
    7172}
     
    8384    [webView setUIDelegate:delegate.get()];
    8485
     86    shouldAccept = true;
     87    navigationFailed = false;
     88    navigationComplete = false;
    8589    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
    8690    TestWebKitAPI::Util::run(&navigationComplete);
     
    8993}
    9094
     95TEST(WebKit, PolicyForNavigationResponseCancelAsynchronously)
     96{
     97    RetainPtr<NSURL> testURL = [[NSBundle mainBundle] URLForResource:@"simple" withExtension:@"html" subdirectory:@"TestWebKitAPI.resources"];
     98
     99    auto webView = adoptNS([[WKWebView alloc] init]);
     100    auto delegate = adoptNS([[TestAsyncNavigationDelegate alloc] init]);
     101    [webView setNavigationDelegate:delegate.get()];
     102    [webView setUIDelegate:delegate.get()];
     103
     104    shouldAccept = false;
     105    navigationFailed = false;
     106    navigationComplete = false;
     107    [webView loadRequest:[NSURLRequest requestWithURL:testURL.get()]];
     108    TestWebKitAPI::Util::run(&navigationComplete);
     109
     110    EXPECT_TRUE(navigationFailed);
     111}
     112
    91113} // namespace TestWebKitAPI
    92114
Note: See TracChangeset for help on using the changeset viewer.