Changeset 119695 in webkit


Ignore:
Timestamp:
Jun 7, 2012 2:11:08 AM (12 years ago)
Author:
Carlos Garcia Campos
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:
Location:
trunk/Source/WebKit2
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r119687 r119695  
     12012-06-06  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [SOUP] WebSoupRequestManager should handle loading errors and zero-length replies
     4        https://bugs.webkit.org/show_bug.cgi?id=88087
     5
     6        Reviewed by Martin Robinson.
     7
     8        * UIProcess/API/C/soup/WKSoupRequestManager.h:
     9        * UIProcess/soup/WebSoupRequestManagerClient.cpp:
     10        (WebKit::WebSoupRequestManagerClient::didFailToLoadURIRequest):
     11        Call didFailToLoadURIRequest in the client if present.
     12        * UIProcess/soup/WebSoupRequestManagerClient.h:
     13        * UIProcess/soup/WebSoupRequestManagerProxy.cpp:
     14        (WebKit::WebSoupRequestManagerProxy::WebSoupRequestManagerProxy):
     15        Initialize m_loadFailed.
     16        (WebKit::WebSoupRequestManagerProxy::didReceiveURIRequestData):
     17        Don't send more data to the web process if the resource failed to
     18        load.
     19        (WebKit::WebSoupRequestManagerProxy::didFailToLoadURIRequest): Set
     20        m_loadFailed and notifiy the client calling didFailToLoadURIRequest.
     21        * UIProcess/soup/WebSoupRequestManagerProxy.h:
     22        * UIProcess/soup/WebSoupRequestManagerProxy.messages.in: Add
     23        DidFailToLoadURIRequest message.
     24        * WebProcess/soup/WebKitSoupRequestGeneric.cpp:
     25        (webkitSoupRequestGenericSendAsync): Pass the cancellable to the
     26        WebSoupRequestManager.
     27        * WebProcess/soup/WebSoupRequestManager.cpp:
     28        (WebKit::WebSoupRequestAsyncData::WebSoupRequestAsyncData): Helper
     29        struct to save requests.
     30        (WebSoupRequestAsyncData): Add a weak pointer to invalidate the
     31        request when it's destroyed before the operation has finished.
     32        (WebKit::WebSoupRequestAsyncData::~WebSoupRequestAsyncData):
     33        Remove the weak pointer.
     34        (WebKit::WebSoupRequestAsyncData::requestFailed): Return whther
     35        the request failed.
     36        (WebKit::WebSoupRequestAsyncData::releaseResult): Return the
     37        result and clear the pointer.
     38        (WebKit::WebSoupRequestManager::didHandleURIRequest): Create and
     39        empty memory stream for zero-length replies instead of creating an
     40        error.
     41        (WebKit::WebSoupRequestManager::didReceiveURIRequestData): If the
     42        request failed and more data expected from the UI process, send a
     43        message to the UI process to notify that the resource load failed.
     44        (WebKit::WebSoupRequestManager::send): Save request information in
     45        the request map.
     46        * WebProcess/soup/WebSoupRequestManager.h:
     47
    1482012-06-06  Andy Estes  <aestes@apple.com>
    249
  • trunk/Source/WebKit2/UIProcess/API/C/soup/WKSoupRequestManager.h

    r116738 r119695  
    3535
    3636typedef void (*WKSoupRequestManagerDidReceiveURIRequestCallback)(WKSoupRequestManagerRef soupRequestManagerRef, WKURLRef urlRef, uint64_t requestID, const void* clientInfo);
     37typedef void (*WKSoupRequestManagerDidFailToLoadURIRequestCallback)(WKSoupRequestManagerRef soupRequestManagerRef, uint64_t requestID, const void* clientInfo);
    3738
    3839struct WKSoupRequestManagerClient {
    39     int                                              version;
    40     const void*                                      clientInfo;
    41     WKSoupRequestManagerDidReceiveURIRequestCallback didReceiveURIRequest;
     40    int                                                 version;
     41    const void*                                         clientInfo;
     42    WKSoupRequestManagerDidReceiveURIRequestCallback    didReceiveURIRequest;
     43    WKSoupRequestManagerDidFailToLoadURIRequestCallback didFailToLoadURIRequest;
    4244};
    4345typedef struct WKSoupRequestManagerClient WKSoupRequestManagerClient;
  • trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.cpp

    r115411 r119695  
    3434}
    3535
     36void WebSoupRequestManagerClient::didFailToLoadURIRequest(WebSoupRequestManagerProxy* soupRequestManager, uint64_t requestID)
     37{
     38    if (m_client.didFailToLoadURIRequest)
     39        m_client.didFailToLoadURIRequest(toAPI(soupRequestManager), requestID, m_client.clientInfo);
     40}
     41
    3642} // namespace WebKit
  • trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerClient.h

    r115411 r119695  
    3232public:
    3333    bool didReceiveURIRequest(WebSoupRequestManagerProxy*, WebURL*, uint64_t requestID);
     34    void didFailToLoadURIRequest(WebSoupRequestManagerProxy*, uint64_t requestID);
    3435};
    3536
  • trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.cpp

    r116738 r119695  
    3434WebSoupRequestManagerProxy::WebSoupRequestManagerProxy(WebContext* context)
    3535    : m_webContext(context)
     36    , m_loadFailed(false)
    3637{
    3738}
     
    6970void WebSoupRequestManagerProxy::didReceiveURIRequestData(const WebData* requestData, uint64_t requestID)
    7071{
     72    if (m_loadFailed)
     73        return;
     74
    7175    ASSERT(m_webContext);
    7276    m_webContext->sendToAllProcesses(Messages::WebSoupRequestManager::DidReceiveURIRequestData(requestData->dataReference(), requestID));
     
    7983}
    8084
     85void WebSoupRequestManagerProxy::didFailToLoadURIRequest(uint64_t requestID)
     86{
     87    m_loadFailed = true;
     88    m_client.didFailToLoadURIRequest(this, requestID);
     89}
     90
    8191} // namespace WebKit
  • trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.h

    r116738 r119695  
    5353    void didHandleURIRequest(const WebData*, uint64_t contentLength, const String& mimeType, uint64_t requestID);
    5454    void didReceiveURIRequestData(const WebData*, uint64_t requestID);
     55    void didFailToLoadURIRequest(uint64_t requestID);
    5556
    5657    void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
     
    6768    WebContext* m_webContext;
    6869    WebSoupRequestManagerClient m_client;
     70    bool m_loadFailed;
    6971};
    7072
  • trunk/Source/WebKit2/UIProcess/soup/WebSoupRequestManagerProxy.messages.in

    r115411 r119695  
    2323messages -> WebSoupRequestManagerProxy {
    2424    DidReceiveURIRequest(WTF::String uriString, uint64_t requestID);
     25    DidFailToLoadURIRequest(uint64_t requestID);
    2526}
  • trunk/Source/WebKit2/WebProcess/soup/WebKitSoupRequestGeneric.cpp

    r115411 r119695  
    4949{
    5050    GSimpleAsyncResult* result = g_simple_async_result_new(G_OBJECT(request), callback, userData, reinterpret_cast<void*>(webkitSoupRequestGenericSendAsync));
    51     WebProcess::shared().soupRequestManager().send(result);
     51    WebProcess::shared().soupRequestManager().send(result, cancellable);
    5252}
    5353
  • trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.cpp

    r118914 r119695  
    4242}
    4343
     44struct WebSoupRequestAsyncData {
     45    WebSoupRequestAsyncData(GSimpleAsyncResult* result, WebKitSoupRequestGeneric* requestGeneric, GCancellable* cancellable)
     46        : result(result)
     47        , request(requestGeneric)
     48        , cancellable(cancellable)
     49    {
     50        // If the struct contains a null request, it is because the request failed.
     51        g_object_add_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
     52    }
     53
     54    ~WebSoupRequestAsyncData()
     55    {
     56        if (request)
     57            g_object_remove_weak_pointer(G_OBJECT(request), reinterpret_cast<void**>(&request));
     58    }
     59
     60    bool requestFailed()
     61    {
     62        return g_cancellable_is_cancelled(cancellable.get()) || !request;
     63    }
     64
     65    GRefPtr<GSimpleAsyncResult> releaseResult()
     66    {
     67        GSimpleAsyncResult* returnValue = result;
     68        result = 0;
     69        return adoptGRef(returnValue);
     70    }
     71
     72    GSimpleAsyncResult* result;
     73    WebKitSoupRequestGeneric* request;
     74    GRefPtr<GCancellable> cancellable;
     75    GRefPtr<GInputStream> stream;
     76};
     77
    4478WebSoupRequestManager::WebSoupRequestManager(WebProcess* process)
    4579    : m_process(process)
     
    79113void WebSoupRequestManager::didHandleURIRequest(const CoreIPC::DataReference& requestData, uint64_t contentLength, const String& mimeType, uint64_t requestID)
    80114{
    81     GRefPtr<GSimpleAsyncResult> result = adoptGRef(m_requestMap.take(requestID));
     115    WebSoupRequestAsyncData* data = m_requestMap.get(requestID);
     116    ASSERT(data);
     117    GRefPtr<GSimpleAsyncResult> result = data->releaseResult();
    82118    ASSERT(result.get());
    83119
    84120    GRefPtr<WebKitSoupRequestGeneric> request = adoptGRef(WEBKIT_SOUP_REQUEST_GENERIC(g_async_result_get_source_object(G_ASYNC_RESULT(result.get()))));
    85     if (requestData.size()) {
    86         webkitSoupRequestGenericSetContentLength(request.get(), contentLength ? contentLength : -1);
    87         webkitSoupRequestGenericSetContentType(request.get(), !mimeType.isEmpty() ? mimeType.utf8().data() : 0);
     121    webkitSoupRequestGenericSetContentLength(request.get(), contentLength ? contentLength : -1);
     122    webkitSoupRequestGenericSetContentType(request.get(), !mimeType.isEmpty() ? mimeType.utf8().data() : 0);
    88123
    89         GInputStream* dataStream;
    90         if (requestData.size() == contentLength) {
    91             // We don't expect more data, so we can just create a GMemoryInputStream with all the data.
    92             dataStream = g_memory_input_stream_new_from_data(g_memdup(requestData.data(), requestData.size()), contentLength, g_free);
    93         } else {
    94             dataStream = webkitSoupRequestInputStreamNew(contentLength);
    95             webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream), requestData.data(), requestData.size());
    96             m_requestStreamMap.set(requestID, dataStream);
    97         }
    98         g_simple_async_result_set_op_res_gpointer(result.get(), dataStream, g_object_unref);
     124    GInputStream* dataStream;
     125    if (!requestData.size()) {
     126        // Empty reply, just create and empty GMemoryInputStream.
     127        dataStream = g_memory_input_stream_new();
     128        m_requestMap.remove(requestID);
     129    } else if (requestData.size() == contentLength) {
     130        // We don't expect more data, so we can just create a GMemoryInputStream with all the data.
     131        dataStream = g_memory_input_stream_new_from_data(g_memdup(requestData.data(), requestData.size()), contentLength, g_free);
     132        m_requestMap.remove(requestID);
    99133    } else {
    100         GOwnPtr<char> uriString(soup_uri_to_string(soup_request_get_uri(SOUP_REQUEST(request.get())), FALSE));
    101         WebCore::ResourceRequest resourceRequest(String::fromUTF8(uriString.get()));
    102         WebCore::ResourceError resourceError(cannotShowURLError(resourceRequest));
    103         g_simple_async_result_set_error(result.get(), g_quark_from_string(resourceError.domain().utf8().data()),
    104                                         resourceError.errorCode(), "%s", resourceError.localizedDescription().utf8().data());
     134        // We expect more data chunks from the UI process.
     135        dataStream = webkitSoupRequestInputStreamNew(contentLength);
     136        data->stream = dataStream;
     137        webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream), requestData.data(), requestData.size());
    105138    }
     139    g_simple_async_result_set_op_res_gpointer(result.get(), dataStream, g_object_unref);
    106140    g_simple_async_result_complete(result.get());
    107141}
     
    109143void WebSoupRequestManager::didReceiveURIRequestData(const CoreIPC::DataReference& requestData, uint64_t requestID)
    110144{
    111     GInputStream* dataStream = m_requestStreamMap.get(requestID);
    112     ASSERT(dataStream);
    113     webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream), requestData.data(), requestData.size());
    114     if (webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(dataStream)))
    115         m_requestStreamMap.remove(requestID);
     145    WebSoupRequestAsyncData* data = m_requestMap.get(requestID);
     146    // The data might have been removed from the request map if a previous chunk failed
     147    // and a new message was sent by the UI process before being notified about the failure.
     148    if (!data)
     149        return;
     150    ASSERT(data->stream.get());
     151
     152    if (data->requestFailed()) {
     153        // ResourceRequest failed or it was cancelled. It doesn't matter here the error or if it was cancelled,
     154        // because that's already handled by the resource handle client, we just want to notify the UI process
     155        // to stop reading data from the user input stream. If UI process already sent all the data we simply
     156        // finish silently.
     157        if (!webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get())))
     158            m_process->connection()->send(Messages::WebSoupRequestManagerProxy::DidFailToLoadURIRequest(requestID), 0);
     159        m_requestMap.remove(requestID);
     160
     161        return;
     162    }
     163
     164    webkitSoupRequestInputStreamAddData(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get()), requestData.data(), requestData.size());
     165    if (webkitSoupRequestInputStreamFinished(WEBKIT_SOUP_REQUEST_INPUT_STREAM(data->stream.get())))
     166        m_requestMap.remove(requestID);
    116167}
    117168
    118 void WebSoupRequestManager::send(GSimpleAsyncResult* result)
     169void WebSoupRequestManager::send(GSimpleAsyncResult* result, GCancellable* cancellable)
    119170{
    120171    GRefPtr<WebKitSoupRequestGeneric> request = adoptGRef(WEBKIT_SOUP_REQUEST_GENERIC(g_async_result_get_source_object(G_ASYNC_RESULT(result))));
     
    123174
    124175    uint64_t requestID = generateSoupRequestID();
    125     m_requestMap.set(requestID, result);
     176    m_requestMap.set(requestID, adoptPtr(new WebSoupRequestAsyncData(result, request.get(), cancellable)));
    126177    m_process->connection()->send(Messages::WebSoupRequestManagerProxy::DidReceiveURIRequest(String::fromUTF8(uriString.get()), requestID), 0);
    127178}
  • trunk/Source/WebKit2/WebProcess/soup/WebSoupRequestManager.h

    r116738 r119695  
    2323#include <wtf/HashMap.h>
    2424#include <wtf/Noncopyable.h>
     25#include <wtf/OwnPtr.h>
    2526#include <wtf/gobject/GRefPtr.h>
    2627#include <wtf/text/WTFString.h>
     
    3940
    4041class WebProcess;
     42struct WebSoupRequestAsyncData;
    4143
    4244class WebSoupRequestManager {
     
    4648    ~WebSoupRequestManager();
    4749
    48     void send(GSimpleAsyncResult*);
     50    void send(GSimpleAsyncResult*, GCancellable*);
    4951    GInputStream* finish(GSimpleAsyncResult*);
    5052
     
    6062    WebProcess* m_process;
    6163    GRefPtr<GPtrArray> m_schemes;
    62     HashMap<uint64_t, GSimpleAsyncResult*> m_requestMap;
    63     HashMap<uint64_t, GInputStream*> m_requestStreamMap;
     64    HashMap<uint64_t, OwnPtr<WebSoupRequestAsyncData> > m_requestMap;
    6465};
    6566
Note: See TracChangeset for help on using the changeset viewer.