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