Changeset 188150 in webkit


Ignore:
Timestamp:
Aug 7, 2015 1:10:42 PM (9 years ago)
Author:
aestes@apple.com
Message:

Crash when following a Google search link to Twitter with Limit Adult Content enabled
https://bugs.webkit.org/show_bug.cgi?id=147651

Reviewed by Brady Eidson.

When a loaded CachedRawResource gets a new client, it synthesizes the callbacks that the new client would have
received while the resource was loading. Unlike a real network load, it synthesizes these callbacks in a single
run loop iteration. When DocumentLoader receives a redirect, and finds substitute data in the app cache for the
redirect URL, it schedules a timer that removes DocumentLoader as a client of the CachedRawResource then
synthesizes its own set of CachedRawResourceClient callbacks. But since CachedRawResource has already delivered
client callbacks before the app cache timer fires, DocumentLoader unexpectedly ends up getting two sets of
client callbacks and badness ensues.

The fix is to let CachedRawResource detect if a redirect will trigger the client to load substitute data. If so,
stop delivering client callbacks.

Layout test to follow.

  • loader/DocumentLoader.cpp:

(WebCore::DocumentLoader::syntheticRedirectReceived): If there is valid substitute data, do not continue.

  • loader/DocumentLoader.h:
  • loader/cache/CachedRawResource.cpp: Returned early if syntheticRedirectReceived() said not to continue.

(WebCore::CachedRawResource::didAddClient):

  • loader/cache/CachedRawResourceClient.h:

(WebCore::CachedRawResourceClient::syntheticRedirectReceived):

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r188148 r188150  
     12015-08-07  Andy Estes  <aestes@apple.com>
     2
     3        Crash when following a Google search link to Twitter with Limit Adult Content enabled
     4        https://bugs.webkit.org/show_bug.cgi?id=147651
     5
     6        Reviewed by Brady Eidson.
     7
     8        When a loaded CachedRawResource gets a new client, it synthesizes the callbacks that the new client would have
     9        received while the resource was loading. Unlike a real network load, it synthesizes these callbacks in a single
     10        run loop iteration. When DocumentLoader receives a redirect, and finds substitute data in the app cache for the
     11        redirect URL, it schedules a timer that removes DocumentLoader as a client of the CachedRawResource then
     12        synthesizes its own set of CachedRawResourceClient callbacks. But since CachedRawResource has already delivered
     13        client callbacks before the app cache timer fires, DocumentLoader unexpectedly ends up getting two sets of
     14        client callbacks and badness ensues.
     15
     16        The fix is to let CachedRawResource detect if a redirect will trigger the client to load substitute data. If so,
     17        stop delivering client callbacks.
     18
     19        Layout test to follow.
     20
     21        * loader/DocumentLoader.cpp:
     22        (WebCore::DocumentLoader::syntheticRedirectReceived): If there is valid substitute data, do not continue.
     23        * loader/DocumentLoader.h:
     24        * loader/cache/CachedRawResource.cpp: Returned early if syntheticRedirectReceived() said not to continue.
     25        (WebCore::CachedRawResource::didAddClient):
     26        * loader/cache/CachedRawResourceClient.h:
     27        (WebCore::CachedRawResourceClient::syntheticRedirectReceived):
     28
    1292015-08-06  Dean Jackson  <dino@apple.com>
    230
  • trunk/Source/WebCore/loader/DocumentLoader.cpp

    r188145 r188150  
    490490}
    491491
     492void DocumentLoader::syntheticRedirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse, bool& shouldContinue)
     493{
     494    redirectReceived(resource, request, redirectResponse);
     495
     496    // If we will soon remove our reference to the CachedRawResource in favor of a SubstituteData load, we don't want to continue receiving synthetic CachedRawResource callbacks.
     497    shouldContinue = !m_substituteData.isValid();
     498}
     499
    492500void DocumentLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
    493501{
  • trunk/Source/WebCore/loader/DocumentLoader.h

    r187620 r188150  
    307307        void mainReceivedError(const ResourceError&);
    308308        WEBCORE_EXPORT virtual void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) override;
     309        WEBCORE_EXPORT virtual void syntheticRedirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&, bool& /* shouldContinue */) override;
    309310        WEBCORE_EXPORT virtual void responseReceived(CachedResource*, const ResourceResponse&) override;
    310311        WEBCORE_EXPORT virtual void dataReceived(CachedResource*, const char* data, int length) override;
  • trunk/Source/WebCore/loader/cache/CachedRawResource.cpp

    r186279 r188150  
    133133        RedirectPair redirect = m_redirectChain[i];
    134134        ResourceRequest request(redirect.m_request);
    135         client->redirectReceived(this, request, redirect.m_redirectResponse);
    136         if (!hasClient(c))
     135        bool shouldContinue = true;
     136        client->syntheticRedirectReceived(this, request, redirect.m_redirectResponse, shouldContinue);
     137        if (!hasClient(c) || !shouldContinue)
    137138            return;
    138139    }
  • trunk/Source/WebCore/loader/cache/CachedRawResourceClient.h

    r162139 r188150  
    4242    virtual void dataReceived(CachedResource*, const char* /* data */, int /* length */) { }
    4343    virtual void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) { }
     44
     45    // In response to a redirect, some clients wish to receive no futher callbacks, but cannot immediately remove themselves as a client.
     46    // Those clients can express their desire to recieve no futher callbacks by setting shouldContinue to false.
     47    virtual void syntheticRedirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& response, bool& /* shouldContinue */) { redirectReceived(resource, request, response); }
    4448#if USE(SOUP)
    4549    virtual char* getOrCreateReadBuffer(CachedResource*, size_t /* requestedSize */, size_t& /* actualSize */) { return 0; }
Note: See TracChangeset for help on using the changeset viewer.