Reviewed by Maciej, Darin.
authordarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jul 2007 16:54:22 +0000 (16:54 +0000)
committerdarin <darin@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 25 Jul 2007 16:54:22 +0000 (16:54 +0000)
        - http://bugs.webkit.org/show_bug.cgi?id=14030

        Add ResourceHandle::setClient to resolve some messiness with handle
        releasing. Clear the client when ResourceLoader is going to release
        the handle to prevent crashes in the case where somebody still holds a
        reference (this doesn't seem to currently happen in practice). Add
        NULL-checking for ResourceHandle implementations using the client.

        * loader/ResourceLoader.cpp:
        (WebCore::ResourceLoader::releaseResources):
        * platform/network/ResourceHandle.cpp:
        (WebCore::ResourceHandle::fireBlockedFailure):
        (WebCore::ResourceHandle::setClient):
        * platform/network/ResourceHandle.h:
        * platform/network/cf/ResourceHandleCFNet.cpp:
        (WebCore::willSendRequest):
        (WebCore::didReceiveResponse):
        (WebCore::didReceiveData):
        (WebCore::didFinishLoading):
        (WebCore::didFail):
        (WebCore::willCacheResponse):
        (WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
        (WebCore::ResourceHandle::receivedCancellation):
        * platform/network/mac/ResourceHandleMac.mm:
        (WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
        (WebCore::ResourceHandle::didCancelAuthenticationChallenge):
        (WebCore::ResourceHandle::receivedCancellation):
        (-[WebCoreResourceHandleAsDelegate connection:willSendRequest:redirectResponse:]):
        (-[WebCoreResourceHandleAsDelegate connection:didReceiveResponse:]):
        (-[WebCoreResourceHandleAsDelegate connection:didReceiveData:lengthReceived:]):
        (-[WebCoreResourceHandleAsDelegate connection:willStopBufferingData:]):
        (-[WebCoreResourceHandleAsDelegate connectionDidFinishLoading:]):
        (-[WebCoreResourceHandleAsDelegate connection:didFailWithError:]):
        (-[WebCoreResourceHandleAsDelegate connection:willCacheResponse:]):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@24624 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/loader/ResourceLoader.cpp
WebCore/platform/network/ResourceHandle.cpp
WebCore/platform/network/ResourceHandle.h
WebCore/platform/network/cf/ResourceHandleCFNet.cpp
WebCore/platform/network/mac/ResourceHandleMac.mm

index ae5ada2..684dff2 100644 (file)
@@ -1,3 +1,42 @@
+2007-07-25  Marvin Decker  <marv.decker@gmail.com>
+
+        Reviewed by Maciej, Darin.
+
+        - http://bugs.webkit.org/show_bug.cgi?id=14030
+
+        Add ResourceHandle::setClient to resolve some messiness with handle
+        releasing. Clear the client when ResourceLoader is going to release
+        the handle to prevent crashes in the case where somebody still holds a
+        reference (this doesn't seem to currently happen in practice). Add
+        NULL-checking for ResourceHandle implementations using the client.
+
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::releaseResources):
+        * platform/network/ResourceHandle.cpp:
+        (WebCore::ResourceHandle::fireBlockedFailure):
+        (WebCore::ResourceHandle::setClient):
+        * platform/network/ResourceHandle.h:
+        * platform/network/cf/ResourceHandleCFNet.cpp:
+        (WebCore::willSendRequest):
+        (WebCore::didReceiveResponse):
+        (WebCore::didReceiveData):
+        (WebCore::didFinishLoading):
+        (WebCore::didFail):
+        (WebCore::willCacheResponse):
+        (WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
+        (WebCore::ResourceHandle::receivedCancellation):
+        * platform/network/mac/ResourceHandleMac.mm:
+        (WebCore::ResourceHandle::didReceiveAuthenticationChallenge):
+        (WebCore::ResourceHandle::didCancelAuthenticationChallenge):
+        (WebCore::ResourceHandle::receivedCancellation):
+        (-[WebCoreResourceHandleAsDelegate connection:willSendRequest:redirectResponse:]):
+        (-[WebCoreResourceHandleAsDelegate connection:didReceiveResponse:]):
+        (-[WebCoreResourceHandleAsDelegate connection:didReceiveData:lengthReceived:]):
+        (-[WebCoreResourceHandleAsDelegate connection:willStopBufferingData:]):
+        (-[WebCoreResourceHandleAsDelegate connectionDidFinishLoading:]):
+        (-[WebCoreResourceHandleAsDelegate connection:didFailWithError:]):
+        (-[WebCoreResourceHandleAsDelegate connection:willCacheResponse:]):
+
 2007-07-25  Maxime Britto  <mbritto@pleyo.com>
 
         Reviewed by Darin.
index 25f8bc0..d758891 100644 (file)
@@ -89,7 +89,13 @@ void ResourceLoader::releaseResources()
 
     m_identifier = 0;
 
-    m_handle = 0;
+    if (m_handle) {
+        // Clear out the ResourceHandle's client so that it doesn't try to call
+        // us back after we release it.
+        m_handle->setClient(0);
+        m_handle = 0;
+    }
+
     m_resourceData = 0;
     m_deferredRequest = ResourceRequest();
 }
index 483bd87..80e6ea6 100644 (file)
@@ -64,7 +64,8 @@ void ResourceHandle::scheduleBlockedFailure()
 
 void ResourceHandle::fireBlockedFailure(Timer<ResourceHandle>* timer)
 {
-    client()->wasBlocked(this);
+    if (client())
+        client()->wasBlocked(this);
     delete timer;
 }
 
@@ -73,6 +74,11 @@ ResourceHandleClient* ResourceHandle::client() const
     return d->m_client;
 }
 
+void ResourceHandle::setClient(ResourceHandleClient* client)
+{
+    d->m_client = client;
+}
+
 const ResourceRequest& ResourceHandle::request() const
 {
     return d->m_request;
index a4e7ebc..f24f85c 100644 (file)
@@ -148,8 +148,11 @@ public:
     
     void clearAuthentication();
     void cancel();
-    
+
+    // The client may be 0, in which case no callbacks will be made.
     ResourceHandleClient* client() const;
+    void setClient(ResourceHandleClient*);
+
     void setDefersLoading(bool);
       
     const ResourceRequest& request() const;
index 3686b26..23d1812 100644 (file)
@@ -66,7 +66,8 @@ CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfReque
     LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().url().ascii());
 
     ResourceRequest request(cfRequest);
-    handle->client()->willSendRequest(handle, request, cfRedirectResponse);
+    if (handle->client())
+        handle->client()->willSendRequest(handle, request, cfRedirectResponse);
 
     cfRequest = request.cfURLRequest();
 
@@ -80,7 +81,8 @@ void didReceiveResponse(CFURLConnectionRef conn, CFURLResponseRef cfResponse, co
 
     LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().url().ascii());
 
-    handle->client()->didReceiveResponse(handle, cfResponse);
+    if (handle->client())
+        handle->client()->didReceiveResponse(handle, cfResponse);
 }
 
 void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLength, const void* clientInfo) 
@@ -91,7 +93,8 @@ void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLen
 
     LOG(Network, "CFNet - didReceiveData(conn=%p, handle=%p, bytes=%d) (%s)", conn, handle, length, handle->request().url().url().ascii());
 
-    handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength);
+    if (handle->client())
+        handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength);
 }
 
 void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo) 
@@ -100,7 +103,8 @@ void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo)
 
     LOG(Network, "CFNet - didFinishLoading(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().url().ascii());
 
-    handle->client()->didFinishLoading(handle);
+    if (handle->client())
+        handle->client()->didFinishLoading(handle);
 }
 
 void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo) 
@@ -109,7 +113,8 @@ void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo)
 
     LOG(Network, "CFNet - didFail(conn=%p, handle=%p, error = %p) (%s)", conn, handle, error, handle->request().url().url().ascii());
 
-    handle->client()->didFail(handle, ResourceError(error));
+    if (handle->client())
+        handle->client()->didFail(handle, ResourceError(error));
 }
 
 CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef conn, CFCachedURLResponseRef cachedResponse, const void* clientInfo) 
@@ -118,7 +123,8 @@ CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef conn, CFCachedURLRes
 
     CacheStoragePolicy policy = static_cast<CacheStoragePolicy>(CFCachedURLResponseGetStoragePolicy(cachedResponse));
 
-    handle->client()->willCacheResponse(handle, policy);
+    if (handle->client())
+        handle->client()->willCacheResponse(handle, policy);
 
     if (static_cast<CFURLCacheStoragePolicy>(policy) != CFCachedURLResponseGetStoragePolicy(cachedResponse))
         cachedResponse = CFCachedURLResponseCreateWithUserInfo(kCFAllocatorDefault, 
@@ -291,7 +297,8 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall
     d->m_currentCFChallenge = challenge.cfURLAuthChallengeRef();
     d->m_currentWebChallenge = AuthenticationChallenge(d->m_currentCFChallenge, this);
     
-    client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
+    if (client())
+        client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
 }
 
 void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential)
@@ -328,7 +335,8 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
     if (challenge != d->m_currentWebChallenge)
         return;
 
-    client()->receivedCancellation(this, challenge);
+    if (client())
+        client()->receivedCancellation(this, challenge);
 }
 
 CFURLConnectionRef ResourceHandle::connection() const
index 4598199..04904b9 100644 (file)
@@ -264,8 +264,9 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall
                                                                                        sender:(id<NSURLAuthenticationChallengeSender>)delegate()];
     d->m_currentWebChallenge = core(webChallenge);
     [webChallenge release];
-    
-    client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
+
+    if (client())
+        client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
 }
 
 void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
@@ -274,7 +275,8 @@ void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChalle
     ASSERT(!d->m_currentWebChallenge.isNull());
     ASSERT(d->m_currentWebChallenge == challenge);
 
-    client()->didCancelAuthenticationChallenge(this, d->m_currentWebChallenge);
+    if (client())
+        client()->didCancelAuthenticationChallenge(this, d->m_currentWebChallenge);
 }
 
 void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential)
@@ -304,7 +306,8 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
     if (challenge != d->m_currentWebChallenge)
         return;
 
-    client()->receivedCancellation(this, challenge);
+    if (client())
+        client()->receivedCancellation(this, challenge);
 }
 
 } // namespace WebCore
@@ -335,7 +338,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
 
 - (NSURLRequest *)connection:(NSURLConnection *)con willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse
 {
-    if (!m_handle)
+    if (!m_handle || !m_handle->client())
         return nil;
     ++inNSURLConnectionCallback;
     ResourceRequest request = newRequest;
@@ -384,7 +387,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
 
 - (void)connection:(NSURLConnection *)con didReceiveResponse:(NSURLResponse *)r
 {
-    if (!m_handle)
+    if (!m_handle || !m_handle->client())
         return;
     ++inNSURLConnectionCallback;
     m_handle->client()->didReceiveResponse(m_handle, r);
@@ -393,7 +396,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
 
 - (void)connection:(NSURLConnection *)con didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived
 {
-    if (!m_handle)
+    if (!m_handle || !m_handle->client())
         return;
     // FIXME: If we get more than 2B bytes in a single chunk, this code won't do the right thing.
     // However, with today's computers and networking speeds, this won't happen in practice.
@@ -405,7 +408,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
 
 - (void)connection:(NSURLConnection *)con willStopBufferingData:(NSData *)data
 {
-    if (!m_handle)
+    if (!m_handle || !m_handle->client())
         return;
     // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
     // However, with today's computers and networking speeds, this won't happen in practice.
@@ -417,7 +420,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
 
 - (void)connectionDidFinishLoading:(NSURLConnection *)con
 {
-    if (!m_handle)
+    if (!m_handle || !m_handle->client())
         return;
     ++inNSURLConnectionCallback;
     m_handle->client()->didFinishLoading(m_handle);
@@ -426,7 +429,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
 
 - (void)connection:(NSURLConnection *)con didFailWithError:(NSError *)error
 {
-    if (!m_handle)
+    if (!m_handle || !m_handle->client())
         return;
     ++inNSURLConnectionCallback;
     m_handle->client()->didFail(m_handle, error);
@@ -439,7 +442,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
     if (isInitializingConnection)
         LOG_ERROR("connection:willCacheResponse: was called inside of [NSURLConnection initWithRequest:delegate:] (4067625)");
 #endif
-    if (!m_handle)
+    if (!m_handle || !m_handle->client())
         return nil;
     ++inNSURLConnectionCallback;