Title: [119695] trunk/Source/WebKit2
Revision
119695
Author
[email protected]
Date
2012-06-07 02:11:08 -0700 (Thu, 07 Jun 2012)

Log Message

[SOUP] WebSoupRequestManager should handle loading errors and zero-length replies
https://bugs.webkit.org/show_bug.cgi?id=88087

Reviewed by Martin Robinson.

* UIProcess/API/C/soup/WKSoupRequestManager.h:
* UIProcess/soup/WebSoupRequestManagerClient.cpp:
(WebKit::WebSoupRequestManagerClient::didFailToLoadURIRequest):
Call didFailToLoadURIRequest in the client if present.
* UIProcess/soup/WebSoupRequestManagerClient.h:
* UIProcess/soup/WebSoupRequestManagerProxy.cpp:
(WebKit::WebSoupRequestManagerProxy::WebSoupRequestManagerProxy):
Initialize m_loadFailed.
(WebKit::WebSoupRequestManagerProxy::didReceiveURIRequestData):
Don't send more data to the web process if the resource failed to
load.
(WebKit::WebSoupRequestManagerProxy::didFailToLoadURIRequest): Set
m_loadFailed and notifiy the client calling didFailToLoadURIRequest.
* UIProcess/soup/WebSoupRequestManagerProxy.h:
* UIProcess/soup/WebSoupRequestManagerProxy.messages.in: Add
DidFailToLoadURIRequest message.
* WebProcess/soup/WebKitSoupRequestGeneric.cpp:
(webkitSoupRequestGenericSendAsync): Pass the cancellable to the
WebSoupRequestManager.
* WebProcess/soup/WebSoupRequestManager.cpp:
(WebKit::WebSoupRequestAsyncData::WebSoupRequestAsyncData): Helper
struct to save requests.
(WebSoupRequestAsyncData): Add a weak pointer to invalidate the
request when it's destroyed before the operation has finished.
(WebKit::WebSoupRequestAsyncData::~WebSoupRequestAsyncData):
Remove the weak pointer.
(WebKit::WebSoupRequestAsyncData::requestFailed): Return whther
the request failed.
(WebKit::WebSoupRequestAsyncData::releaseResult): Return the
result and clear the pointer.
(WebKit::WebSoupRequestManager::didHandleURIRequest): Create and
empty memory stream for zero-length replies instead of creating an
error.
(WebKit::WebSoupRequestManager::didReceiveURIRequestData): If the
request failed and more data expected from the UI process, send a
message to the UI process to notify that the resource load failed.
(WebKit::WebSoupRequestManager::send): Save request information in
the request map.
* WebProcess/soup/WebSoupRequestManager.h:

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (119694 => 119695)


--- trunk/Source/WebKit2/ChangeLog	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/ChangeLog	2012-06-07 09:11:08 UTC (rev 119695)
@@ -1,3 +1,50 @@
+2012-06-06  Carlos Garcia Campos  <[email protected]>
+
+        [SOUP] WebSoupRequestManager should handle loading errors and zero-length replies
+        https://bugs.webkit.org/show_bug.cgi?id=88087
+
+        Reviewed by Martin Robinson.
+
+        * UIProcess/API/C/soup/WKSoupRequestManager.h:
+        * UIProcess/soup/WebSoupRequestManagerClient.cpp:
+        (WebKit::WebSoupRequestManagerClient::didFailToLoadURIRequest):
+        Call didFailToLoadURIRequest in the client if present.
+        * UIProcess/soup/WebSoupRequestManagerClient.h:
+        * UIProcess/soup/WebSoupRequestManagerProxy.cpp:
+        (WebKit::WebSoupRequestManagerProxy::WebSoupRequestManagerProxy):
+        Initialize m_loadFailed.
+        (WebKit::WebSoupRequestManagerProxy::didReceiveURIRequestData):
+        Don't send more data to the web process if the resource failed to
+        load.
+        (WebKit::WebSoupRequestManagerProxy::didFailToLoadURIRequest): Set
+        m_loadFailed and notifiy the client calling didFailToLoadURIRequest.
+        * UIProcess/soup/WebSoupRequestManagerProxy.h:
+        * UIProcess/soup/WebSoupRequestManagerProxy.messages.in: Add
+        DidFailToLoadURIRequest message.
+        * WebProcess/soup/WebKitSoupRequestGeneric.cpp:
+        (webkitSoupRequestGenericSendAsync): Pass the cancellable to the
+        WebSoupRequestManager.
+        * WebProcess/soup/WebSoupRequestManager.cpp:
+        (WebKit::WebSoupRequestAsyncData::WebSoupRequestAsyncData): Helper
+        struct to save requests.
+        (WebSoupRequestAsyncData): Add a weak pointer to invalidate the
+        request when it's destroyed before the operation has finished.
+        (WebKit::WebSoupRequestAsyncData::~WebSoupRequestAsyncData):
+        Remove the weak pointer.
+        (WebKit::WebSoupRequestAsyncData::requestFailed): Return whther
+        the request failed.
+        (WebKit::WebSoupRequestAsyncData::releaseResult): Return the
+        result and clear the pointer.
+        (WebKit::WebSoupRequestManager::didHandleURIRequest): Create and
+        empty memory stream for zero-length replies instead of creating an
+        error.
+        (WebKit::WebSoupRequestManager::didReceiveURIRequestData): If the
+        request failed and more data expected from the UI process, send a
+        message to the UI process to notify that the resource load failed.
+        (WebKit::WebSoupRequestManager::send): Save request information in
+        the request map.
+        * WebProcess/soup/WebSoupRequestManager.h:
+
 2012-06-06  Andy Estes  <[email protected]>
 
         Wrap uppercaseWord, lowercaseWord, and capitalizeWord with USE(APPKIT)

Modified: trunk/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h (119694 => 119695)


--- trunk/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h	2012-06-07 09:11:08 UTC (rev 119695)
@@ -34,11 +34,13 @@
 #endif
 
 typedef void (*WKSoupRequestManagerDidReceiveURIRequestCallback)(WKSoupRequestManagerRef soupRequestManagerRef, WKURLRef urlRef, uint64_t requestID, const void* clientInfo);
+typedef void (*WKSoupRequestManagerDidFailToLoadURIRequestCallback)(WKSoupRequestManagerRef soupRequestManagerRef, uint64_t requestID, const void* clientInfo);
 
 struct WKSoupRequestManagerClient {
-    int                                              version;
-    const void*                                      clientInfo;
-    WKSoupRequestManagerDidReceiveURIRequestCallback didReceiveURIRequest;
+    int                                                 version;
+    const void*                                         clientInfo;
+    WKSoupRequestManagerDidReceiveURIRequestCallback    didReceiveURIRequest;
+    WKSoupRequestManagerDidFailToLoadURIRequestCallback didFailToLoadURIRequest;
 };
 typedef struct WKSoupRequestManagerClient WKSoupRequestManagerClient;
 

Modified: trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.cpp (119694 => 119695)


--- trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.cpp	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.cpp	2012-06-07 09:11:08 UTC (rev 119695)
@@ -33,4 +33,10 @@
     return true;
 }
 
+void WebSoupRequestManagerClient::didFailToLoadURIRequest(WebSoupRequestManagerProxy* soupRequestManager, uint64_t requestID)
+{
+    if (m_client.didFailToLoadURIRequest)
+        m_client.didFailToLoadURIRequest(toAPI(soupRequestManager), requestID, m_client.clientInfo);
+}
+
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.h (119694 => 119695)


--- trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.h	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.h	2012-06-07 09:11:08 UTC (rev 119695)
@@ -31,6 +31,7 @@
 class WebSoupRequestManagerClient : public APIClient<WKSoupRequestManagerClient, kWKSoupRequestManagerClientCurrentVersion> {
 public:
     bool didReceiveURIRequest(WebSoupRequestManagerProxy*, WebURL*, uint64_t requestID);
+    void didFailToLoadURIRequest(WebSoupRequestManagerProxy*, uint64_t requestID);
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp (119694 => 119695)


--- trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp	2012-06-07 09:11:08 UTC (rev 119695)
@@ -33,6 +33,7 @@
 
 WebSoupRequestManagerProxy::WebSoupRequestManagerProxy(WebContext* context)
     : m_webContext(context)
+    , m_loadFailed(false)
 {
 }
 
@@ -68,6 +69,9 @@
 
 void WebSoupRequestManagerProxy::didReceiveURIRequestData(const WebData* requestData, uint64_t requestID)
 {
+    if (m_loadFailed)
+        return;
+
     ASSERT(m_webContext);
     m_webContext->sendToAllProcesses(Messages::WebSoupRequestManager::DidReceiveURIRequestData(requestData->dataReference(), requestID));
 }
@@ -78,4 +82,10 @@
         didHandleURIRequest(WebData::create(0, 0).get(), 0, String(), requestID);
 }
 
+void WebSoupRequestManagerProxy::didFailToLoadURIRequest(uint64_t requestID)
+{
+    m_loadFailed = true;
+    m_client.didFailToLoadURIRequest(this, requestID);
+}
+
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h (119694 => 119695)


--- trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h	2012-06-07 09:11:08 UTC (rev 119695)
@@ -52,6 +52,7 @@
     void registerURIScheme(const String& scheme);
     void didHandleURIRequest(const WebData*, uint64_t contentLength, const String& mimeType, uint64_t requestID);
     void didReceiveURIRequestData(const WebData*, uint64_t requestID);
+    void didFailToLoadURIRequest(uint64_t requestID);
 
     void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
 
@@ -66,6 +67,7 @@
 
     WebContext* m_webContext;
     WebSoupRequestManagerClient m_client;
+    bool m_loadFailed;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.messages.in (119694 => 119695)


--- trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.messages.in	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.messages.in	2012-06-07 09:11:08 UTC (rev 119695)
@@ -22,4 +22,5 @@
 
 messages -> WebSoupRequestManagerProxy {
     DidReceiveURIRequest(WTF::String uriString, uint64_t requestID);
+    DidFailToLoadURIRequest(uint64_t requestID);
 }

Modified: trunk/Source/WebKit2/WebProcess/soup/WebKitSoupRequestGeneric.cpp (119694 => 119695)


--- trunk/Source/WebKit2/WebProcess/soup/WebKitSoupRequestGeneric.cpp	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/WebProcess/soup/WebKitSoupRequestGeneric.cpp	2012-06-07 09:11:08 UTC (rev 119695)
@@ -48,7 +48,7 @@
 static void webkitSoupRequestGenericSendAsync(SoupRequest* request, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData)
 {
     GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(request), callback, userData, reinterpret_cast<void*>(webkitSoupRequestGenericSendAsync));
-    WebProcess::shared().soupRequestManager().send(result);
+    WebProcess::shared().soupRequestManager().send(result, cancellable);
 }
 
 static GInputStream* webkitSoupRequestGenericSendFinish(SoupRequest* request, GAsyncResult* result, GError** error)

Modified: trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.cpp (119694 => 119695)


--- trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.cpp	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.cpp	2012-06-07 09:11:08 UTC (rev 119695)
@@ -41,6 +41,40 @@
     return uniqueSoupRequestID++;
 }
 
+struct WebSoupRequestAsyncData {
+    WebSoupRequestAsyncData(GSimpleAsyncResult* result, WebKitSoupRequestGeneric* requestGeneric, GCancellable* cancellable)
+        : result(result)
+        , request(requestGeneric)
+        , cancellable(cancellable)
+    {
+        // If the struct contains a null request, it is because the request failed.
+        g_object_add_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
+    }
+
+    ~WebSoupRequestAsyncData()
+    {
+        if (request)
+            g_object_remove_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
+    }
+
+    bool requestFailed()
+    {
+        return g_cancellable_is_cancelled(cancellable.get()) || !request;
+    }
+
+    GRefPtr<GSimpleAsyncResult> releaseResult()
+    {
+        GSimpleAsyncResult* returnValue = result;
+        result = 0;
+        return adoptGRef(returnValue);
+    }
+
+    GSimpleAsyncResult* result;
+    WebKitSoupRequestGeneric* request;
+    GRefPtr<GCancellable> cancellable;
+    GRefPtr<GInputStream> stream;
+};
+
 WebSoupRequestManager::WebSoupRequestManager(WebProcess* process)
     : m_process(process)
     , m_schemes(adoptGRef(g_ptr_array_new_with_free_func(g_free)))
@@ -78,51 +112,68 @@
 
 void WebSoupRequestManager::didHandleURIRequest(const CoreIPC::DataReference& requestData, uint64_t contentLength, const String& mimeType, uint64_t requestID)
 {
-    GRefPtr<GSimpleAsyncResult> result = adoptGRef(m_requestMap.take(requestID));
+    WebSoupRequestAsyncData* data = ""
+    ASSERT(data);
+    GRefPtr<GSimpleAsyncResult> result = data->releaseResult();
     ASSERT(result.get());
 
     GRefPtr<WebKitSoupRequestGeneric> request = adoptGRef(WEBKIT_SOUP_REQUEST_GENERIC(g_async_result_get_source_object(G_ASYNC_RESULT(result.get()))));
-    if (requestData.size()) {
-        webkitSoupRequestGenericSetContentLength(request.get(), contentLength ? contentLength : -1);
-        webkitSoupRequestGenericSetContentType(request.get(), !mimeType.isEmpty() ? mimeType.utf8().data() : 0);
+    webkitSoupRequestGenericSetContentLength(request.get(), contentLength ? contentLength : -1);
+    webkitSoupRequestGenericSetContentType(request.get(), !mimeType.isEmpty() ? mimeType.utf8().data() : 0);
 
-        GInputStream* dataStream;
-        if (requestData.size() == contentLength) {
-            // We don't expect more data, so we can just create a GMemoryInputStream with all the data.
-            dataStream = g_memory_input_stream_new_from_data(g_memdup(requestData.data(), requestData.size()), contentLength, g_free);
-        } else {
-            dataStream = webkitSoupRequestInputStreamNew(contentLength);
-            webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream), requestData.data(), requestData.size());
-            m_requestStreamMap.set(requestID, dataStream);
-        }
-        g_simple_async_result_set_op_res_gpointer(result.get(), dataStream, g_object_unref);
+    GInputStream* dataStream;
+    if (!requestData.size()) {
+        // Empty reply, just create and empty GMemoryInputStream.
+        dataStream = g_memory_input_stream_new();
+        m_requestMap.remove(requestID);
+    } else if (requestData.size() == contentLength) {
+        // We don't expect more data, so we can just create a GMemoryInputStream with all the data.
+        dataStream = g_memory_input_stream_new_from_data(g_memdup(requestData.data(), requestData.size()), contentLength, g_free);
+        m_requestMap.remove(requestID);
     } else {
-        GOwnPtr<char> uriString(soup_uri_to_string(soup_request_get_uri(SOUP_REQUEST(request.get())), FALSE));
-        WebCore::ResourceRequest resourceRequest(String::fromUTF8(uriString.get()));
-        WebCore::ResourceError resourceError(cannotShowURLError(resourceRequest));
-        g_simple_async_result_set_error(result.get(), g_quark_from_string(resourceError.domain().utf8().data()),
-                                        resourceError.errorCode(), "%s", resourceError.localizedDescription().utf8().data());
+        // We expect more data chunks from the UI process.
+        dataStream = webkitSoupRequestInputStreamNew(contentLength);
+        data->stream = dataStream;
+        webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream), requestData.data(), requestData.size());
     }
+    g_simple_async_result_set_op_res_gpointer(result.get(), dataStream, g_object_unref);
     g_simple_async_result_complete(result.get());
 }
 
 void WebSoupRequestManager::didReceiveURIRequestData(const CoreIPC::DataReference& requestData, uint64_t requestID)
 {
-    GInputStream* dataStream = m_requestStreamMap.get(requestID);
-    ASSERT(dataStream);
-    webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream), requestData.data(), requestData.size());
-    if (webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream)))
-        m_requestStreamMap.remove(requestID);
+    WebSoupRequestAsyncData* data = ""
+    // The data might have been removed from the request map if a previous chunk failed
+    // and a new message was sent by the UI process before being notified about the failure.
+    if (!data)
+        return;
+    ASSERT(data->stream.get());
+
+    if (data->requestFailed()) {
+        // ResourceRequest failed or it was cancelled. It doesn't matter here the error or if it was cancelled,
+        // because that's already handled by the resource handle client, we just want to notify the UI process
+        // to stop reading data from the user input stream. If UI process already sent all the data we simply
+        // finish silently.
+        if (!webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get())))
+            m_process->connection()->send(Messages::WebSoupRequestManagerProxy::DidFailToLoadURIRequest(requestID), 0);
+        m_requestMap.remove(requestID);
+
+        return;
+    }
+
+    webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), requestData.data(), requestData.size());
+    if (webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get())))
+        m_requestMap.remove(requestID);
 }
 
-void WebSoupRequestManager::send(GSimpleAsyncResult* result)
+void WebSoupRequestManager::send(GSimpleAsyncResult* result, GCancellable* cancellable)
 {
     GRefPtr<WebKitSoupRequestGeneric> request = adoptGRef(WEBKIT_SOUP_REQUEST_GENERIC(g_async_result_get_source_object(G_ASYNC_RESULT(result))));
     SoupURI* uri = soup_request_get_uri(SOUP_REQUEST(request.get()));
     GOwnPtr<char> uriString(soup_uri_to_string(uri, FALSE));
 
     uint64_t requestID = generateSoupRequestID();
-    m_requestMap.set(requestID, result);
+    m_requestMap.set(requestID, adoptPtr(new WebSoupRequestAsyncData(result, request.get(), cancellable)));
     m_process->connection()->send(Messages::WebSoupRequestManagerProxy::DidReceiveURIRequest(String::fromUTF8(uriString.get()), requestID), 0);
 }
 

Modified: trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.h (119694 => 119695)


--- trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.h	2012-06-07 08:48:25 UTC (rev 119694)
+++ trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.h	2012-06-07 09:11:08 UTC (rev 119695)
@@ -22,6 +22,7 @@
 
 #include <wtf/HashMap.h>
 #include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
 #include <wtf/gobject/GRefPtr.h>
 #include <wtf/text/WTFString.h>
 
@@ -38,6 +39,7 @@
 namespace WebKit {
 
 class WebProcess;
+struct WebSoupRequestAsyncData;
 
 class WebSoupRequestManager {
     WTF_MAKE_NONCOPYABLE(WebSoupRequestManager);
@@ -45,7 +47,7 @@
     explicit WebSoupRequestManager(WebProcess*);
     ~WebSoupRequestManager();
 
-    void send(GSimpleAsyncResult*);
+    void send(GSimpleAsyncResult*, GCancellable*);
     GInputStream* finish(GSimpleAsyncResult*);
 
     void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
@@ -59,8 +61,7 @@
 
     WebProcess* m_process;
     GRefPtr<GPtrArray> m_schemes;
-    HashMap<uint64_t, GSimpleAsyncResult*> m_requestMap;
-    HashMap<uint64_t, GInputStream*> m_requestStreamMap;
+    HashMap<uint64_t, OwnPtr<WebSoupRequestAsyncData> > m_requestMap;
 };
 
 } // namespace WebKit
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to