Title: [124456] trunk/Source/WebKit2
Revision
124456
Author
[email protected]
Date
2012-08-02 08:01:14 -0700 (Thu, 02 Aug 2012)

Log Message

[GTK] No main resource in WebView on load committed when page has been loaded from history cache
https://bugs.webkit.org/show_bug.cgi?id=91482

Reviewed by Martin Robinson.

We assume that on load committed, we already have a main resource
in the web view, and it has already received a response. This is
not true for pages loaded from the history cache, so when going
back/forward, we don't have a main resource when the
load-committed signal is emitted. We must ensure that the loading
process documented in the API is the same for pages loaded from
the history cache too.

* UIProcess/API/gtk/WebKitLoaderClient.cpp:
(didCommitLoadForFrame): Call webkitWebViewLoadChanged() and let
the web view handle the certificate.
* UIProcess/API/gtk/WebKitWebResource.cpp:
(webkitWebResourceGetFrame): Helper private function to easily get
the WKFrame associated with a WebResource.
* UIProcess/API/gtk/WebKitWebResourcePrivate.h:
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewDisconnectMainResourceResponseChangedSignalHandler):
Disconnect the notify::response signal of the main resource.
(webkitWebViewFinalize): Call
webkitWebViewDisconnectMainResourceResponseChangedSignalHandler().
(setCertificateToMainResource): Set the TLS certificate on the
response of the main resource.
(webkitWebViewEmitLoadChanged): Helper function to emit
load-chancged signal.
(webkitWebViewEmitDelayedLoadEvents): If we were waiting for the
main resource, emit the signals that were delayed.
(webkitWebViewLoadChanged): Do not emit committed or finished if
we are still waiting for the main resource. Set the TLS
certificate if we already have a main resource or wait until we
have the main resource with a response.
(mainResourceResponseChangedCallback): Emitted when the main
resource received the response. Set the certificate on the
response and emit load signals delayed.
(waitForMainResourceResponseIfWaitingForResource): If we are
waiting for the main resource, connect to the notify::response
signal of the WebResource to make sure it has a response already
when load signal delayed are emitted.
(webkitWebViewResourceLoadStarted): Call
waitForMainResourceResponseIfWaitingForResource().
* UIProcess/API/gtk/tests/LoadTrackingTest.cpp:
(loadChangedCallback):
(LoadTrackingTest::goBack):
(LoadTrackingTest::goForward):
* UIProcess/API/gtk/tests/LoadTrackingTest.h:
(LoadTrackingTest):
* UIProcess/API/gtk/tests/TestLoaderClient.cpp:
(testWebViewHistoryLoad):
(serverCallback):
(beforeAll):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (124455 => 124456)


--- trunk/Source/WebKit2/ChangeLog	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/ChangeLog	2012-08-02 15:01:14 UTC (rev 124456)
@@ -1,3 +1,60 @@
+2012-08-02  Carlos Garcia Campos  <[email protected]>
+
+        [GTK] No main resource in WebView on load committed when page has been loaded from history cache
+        https://bugs.webkit.org/show_bug.cgi?id=91482
+
+        Reviewed by Martin Robinson.
+
+        We assume that on load committed, we already have a main resource
+        in the web view, and it has already received a response. This is
+        not true for pages loaded from the history cache, so when going
+        back/forward, we don't have a main resource when the
+        load-committed signal is emitted. We must ensure that the loading
+        process documented in the API is the same for pages loaded from
+        the history cache too.
+
+        * UIProcess/API/gtk/WebKitLoaderClient.cpp:
+        (didCommitLoadForFrame): Call webkitWebViewLoadChanged() and let
+        the web view handle the certificate.
+        * UIProcess/API/gtk/WebKitWebResource.cpp:
+        (webkitWebResourceGetFrame): Helper private function to easily get
+        the WKFrame associated with a WebResource.
+        * UIProcess/API/gtk/WebKitWebResourcePrivate.h:
+        * UIProcess/API/gtk/WebKitWebView.cpp:
+        (webkitWebViewDisconnectMainResourceResponseChangedSignalHandler):
+        Disconnect the notify::response signal of the main resource.
+        (webkitWebViewFinalize): Call
+        webkitWebViewDisconnectMainResourceResponseChangedSignalHandler().
+        (setCertificateToMainResource): Set the TLS certificate on the
+        response of the main resource.
+        (webkitWebViewEmitLoadChanged): Helper function to emit
+        load-chancged signal.
+        (webkitWebViewEmitDelayedLoadEvents): If we were waiting for the
+        main resource, emit the signals that were delayed.
+        (webkitWebViewLoadChanged): Do not emit committed or finished if
+        we are still waiting for the main resource. Set the TLS
+        certificate if we already have a main resource or wait until we
+        have the main resource with a response.
+        (mainResourceResponseChangedCallback): Emitted when the main
+        resource received the response. Set the certificate on the
+        response and emit load signals delayed.
+        (waitForMainResourceResponseIfWaitingForResource): If we are
+        waiting for the main resource, connect to the notify::response
+        signal of the WebResource to make sure it has a response already
+        when load signal delayed are emitted.
+        (webkitWebViewResourceLoadStarted): Call
+        waitForMainResourceResponseIfWaitingForResource().
+        * UIProcess/API/gtk/tests/LoadTrackingTest.cpp:
+        (loadChangedCallback):
+        (LoadTrackingTest::goBack):
+        (LoadTrackingTest::goForward):
+        * UIProcess/API/gtk/tests/LoadTrackingTest.h:
+        (LoadTrackingTest):
+        * UIProcess/API/gtk/tests/TestLoaderClient.cpp:
+        (testWebViewHistoryLoad):
+        (serverCallback):
+        (beforeAll):
+
 2012-08-02  Andras Becsi  <[email protected]>
 
         [Qt][WK2] Click, mouse and links rely on touch mocking.

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp (124455 => 124456)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitLoaderClient.cpp	2012-08-02 15:01:14 UTC (rev 124456)
@@ -65,16 +65,7 @@
     if (!WKFrameIsMainFrame(frame))
         return;
 
-    WebKitWebView* webView = WEBKIT_WEB_VIEW(clientInfo);
-    WebKitWebResource* resource = webkit_web_view_get_main_resource(webView);
-    if (resource) {
-        // We might not have a resource if this load is a content replacement.
-        // FIXME: For some reason, when going back/forward this callback is emitted even before
-        // didInitiateLoadForResource(), so we don't have a main resource at this point either.
-        webkitURIResponseSetCertificateInfo(webkit_web_resource_get_response(resource), WKFrameGetCertificateInfo(frame));
-    }
-
-    webkitWebViewLoadChanged(webView, WEBKIT_LOAD_COMMITTED);
+    webkitWebViewLoadChanged(WEBKIT_WEB_VIEW(clientInfo), WEBKIT_LOAD_COMMITTED);
 }
 
 static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void* clientInfo)

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp (124455 => 124456)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebResource.cpp	2012-08-02 15:01:14 UTC (rev 124456)
@@ -243,6 +243,11 @@
     g_signal_emit(resource, signals[FINISHED], 0, NULL);
 }
 
+WKFrameRef webkitWebResourceGetFrame(WebKitWebResource* resource)
+{
+    return resource->priv->wkFrame.get();
+}
+
 /**
  * webkit_web_resource_get_uri:
  * @resource: a #WebKitWebResource

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h (124455 => 124456)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebResourcePrivate.h	2012-08-02 15:01:14 UTC (rev 124456)
@@ -29,6 +29,7 @@
 void webkitWebResourceNotifyProgress(WebKitWebResource*, guint64 bytesReceived);
 void webkitWebResourceFinished(WebKitWebResource*);
 void webkitWebResourceFailed(WebKitWebResource*, GError*);
+WKFrameRef webkitWebResourceGetFrame(WebKitWebResource*);
 
 
 #endif // WebKitWebResourcePrivate_h

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp (124455 => 124456)


--- trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp	2012-08-02 15:01:14 UTC (rev 124456)
@@ -124,6 +124,10 @@
     CString activeURI;
     ReplaceContentStatus replaceContentStatus;
 
+    bool waitingForMainResource;
+    gulong mainResourceResponseHandlerID;
+    WebKitLoadEvent lastDelayedEvent;
+
     GRefPtr<WebKitBackForwardList> backForwardList;
     GRefPtr<WebKitSettings> settings;
     GRefPtr<WebKitWindowProperties> windowProperties;
@@ -268,6 +272,14 @@
 
 }
 
+static void webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(WebKitWebView* webView)
+{
+    WebKitWebViewPrivate* priv = webView->priv;
+    if (priv->mainResourceResponseHandlerID)
+        g_signal_handler_disconnect(priv->mainResource.get(), priv->mainResourceResponseHandlerID);
+    priv->mainResourceResponseHandlerID = 0;
+}
+
 static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request)
 {
     GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request);
@@ -382,7 +394,8 @@
 
 static void webkitWebViewFinalize(GObject* object)
 {
-    WebKitWebViewPrivate* priv = WEBKIT_WEB_VIEW(object)->priv;
+    WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
+    WebKitWebViewPrivate* priv = webView->priv;
 
     if (priv->_javascript_GlobalContext)
         JSGlobalContextRelease(priv->_javascript_GlobalContext);
@@ -391,7 +404,8 @@
     if (priv->modalLoop && g_main_loop_is_running(priv->modalLoop.get()))
         g_main_loop_quit(priv->modalLoop.get());
 
-    webkitWebViewDisconnectSettingsSignalHandlers(WEBKIT_WEB_VIEW(object));
+    webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
+    webkitWebViewDisconnectSettingsSignalHandlers(webView);
 
     priv->~WebKitWebViewPrivate();
     G_OBJECT_CLASS(webkit_web_view_parent_class)->finalize(object);
@@ -1112,20 +1126,68 @@
     return false;
 }
 
+static void setCertificateToMainResource(WebKitWebView* webView)
+{
+    WebKitWebViewPrivate* priv = webView->priv;
+    ASSERT(priv->mainResource.get());
+
+    webkitURIResponseSetCertificateInfo(webkit_web_resource_get_response(priv->mainResource.get()),
+                                        WKFrameGetCertificateInfo(webkitWebResourceGetFrame(priv->mainResource.get())));
+}
+
+static void webkitWebViewEmitLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
+{
+    if (loadEvent == WEBKIT_LOAD_FINISHED) {
+        webView->priv->waitingForMainResource = false;
+        webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
+    } else
+        webkitWebViewUpdateURI(webView);
+    g_signal_emit(webView, signals[LOAD_CHANGED], 0, loadEvent);
+}
+
+static void webkitWebViewEmitDelayedLoadEvents(WebKitWebView* webView)
+{
+    WebKitWebViewPrivate* priv = webView->priv;
+    if (!priv->waitingForMainResource)
+        return;
+    ASSERT(priv->lastDelayedEvent == WEBKIT_LOAD_COMMITTED || priv->lastDelayedEvent == WEBKIT_LOAD_FINISHED);
+
+    if (priv->lastDelayedEvent == WEBKIT_LOAD_FINISHED)
+        webkitWebViewEmitLoadChanged(webView, WEBKIT_LOAD_COMMITTED);
+    webkitWebViewEmitLoadChanged(webView, priv->lastDelayedEvent);
+    priv->waitingForMainResource = false;
+}
+
 void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
 {
     if (loadEvent == WEBKIT_LOAD_STARTED) {
+        // Finish a possible previous load waiting for main resource.
+        webkitWebViewEmitDelayedLoadEvents(webView);
+
         webView->priv->loadingResourcesMap.clear();
         webView->priv->mainResource = 0;
-    } else if (loadEvent == WEBKIT_LOAD_COMMITTED)
+        webView->priv->waitingForMainResource = false;
+    } else if (loadEvent == WEBKIT_LOAD_COMMITTED) {
         webView->priv->subresourcesMap.clear();
+        if (webView->priv->replaceContentStatus != ReplacingContent) {
+            if (!webView->priv->mainResource) {
+                // When a page is loaded from the history cache, the main resource load callbacks
+                // are called when the main frame load is finished. We want to make sure there's a
+                // main resource available when load has been committed, so we delay the emission of
+                // load-changed signal until main resource object has been created.
+                webView->priv->waitingForMainResource = true;
+            } else
+                setCertificateToMainResource(webView);
+        }
+    }
 
     if (updateReplaceContentStatus(webView, loadEvent))
         return;
 
-    if (loadEvent != WEBKIT_LOAD_FINISHED)
-        webkitWebViewUpdateURI(webView);
-    g_signal_emit(webView, signals[LOAD_CHANGED], 0, loadEvent);
+    if (webView->priv->waitingForMainResource)
+        webView->priv->lastDelayedEvent = loadEvent;
+    else
+        webkitWebViewEmitLoadChanged(webView, loadEvent);
 }
 
 void webkitWebViewLoadFailed(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError *error)
@@ -1269,6 +1331,24 @@
     g_signal_connect(printOperation.leakRef(), "finished", G_CALLBACK(g_object_unref), 0);
 }
 
+static void mainResourceResponseChangedCallback(WebKitWebResource*, GParamSpec*, WebKitWebView* webView)
+{
+    webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
+    setCertificateToMainResource(webView);
+    webkitWebViewEmitDelayedLoadEvents(webView);
+}
+
+static void waitForMainResourceResponseIfWaitingForResource(WebKitWebView* webView)
+{
+    WebKitWebViewPrivate* priv = webView->priv;
+    if (!priv->waitingForMainResource)
+        return;
+
+    webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
+    priv->mainResourceResponseHandlerID =
+        g_signal_connect(priv->mainResource.get(), "notify::response", G_CALLBACK(mainResourceResponseChangedCallback), webView);
+}
+
 static inline bool webkitWebViewIsReplacingContentOrDidReplaceContent(WebKitWebView* webView)
 {
     return (webView->priv->replaceContentStatus == ReplacingContent || webView->priv->replaceContentStatus == DidReplaceContent);
@@ -1281,8 +1361,10 @@
 
     WebKitWebViewPrivate* priv = webView->priv;
     WebKitWebResource* resource = webkitWebResourceCreate(wkFrame, request, isMainResource);
-    if (WKFrameIsMainFrame(wkFrame) && (isMainResource || !priv->mainResource))
+    if (WKFrameIsMainFrame(wkFrame) && (isMainResource || !priv->mainResource)) {
         priv->mainResource = resource;
+        waitForMainResourceResponseIfWaitingForResource(webView);
+    }
     priv->loadingResourcesMap.set(resourceIdentifier, adoptGRef(resource));
     g_signal_emit(webView, signals[RESOURCE_LOAD_STARTED], 0, resource, request);
 }

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp (124455 => 124456)


--- trunk/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.cpp	2012-08-02 15:01:14 UTC (rev 124456)
@@ -35,10 +35,17 @@
             g_assert_cmpstr(test->m_redirectURI.data(), ==, test->m_activeURI.data());
         test->provisionalLoadReceivedServerRedirect();
         break;
-    case WEBKIT_LOAD_COMMITTED:
+    case WEBKIT_LOAD_COMMITTED: {
         g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
+
+        // Check that on committed we always have a main resource with a response.
+        WebKitWebResource* resource = webkit_web_view_get_main_resource(webView);
+        g_assert(resource);
+        g_assert(webkit_web_resource_get_response(resource));
+
         test->loadCommitted();
         break;
+    }
     case WEBKIT_LOAD_FINISHED:
         if (!test->m_loadFailed)
             g_assert_cmpstr(test->m_activeURI.data(), ==, webkit_web_view_get_uri(webView));
@@ -170,3 +177,17 @@
     m_estimatedProgress = 0;
     webkit_web_view_reload(m_webView);
 }
+
+void LoadTrackingTest::goBack()
+{
+    m_loadEvents.clear();
+    m_estimatedProgress = 0;
+    WebViewTest::goBack();
+}
+
+void LoadTrackingTest::goForward()
+{
+    m_loadEvents.clear();
+    m_estimatedProgress = 0;
+    WebViewTest::goForward();
+}

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h (124455 => 124456)


--- trunk/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/tests/LoadTrackingTest.h	2012-08-02 15:01:14 UTC (rev 124456)
@@ -44,6 +44,8 @@
     void loadPlainText(const char* plainText);
     void loadRequest(WebKitURIRequest*);
     void reload();
+    void goBack();
+    void goForward();
 
     void setRedirectURI(const char* uri) { m_redirectURI = uri; }
 

Modified: trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp (124455 => 124456)


--- trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp	2012-08-02 14:42:30 UTC (rev 124455)
+++ trunk/Source/WebKit2/UIProcess/API/gtk/tests/TestLoaderClient.cpp	2012-08-02 15:01:14 UTC (rev 124456)
@@ -144,6 +144,26 @@
     g_assert_cmpfloat(test->m_estimatedProgress, ==, 1);
 }
 
+static void testWebViewHistoryLoad(LoadTrackingTest* test, gconstpointer)
+{
+    test->loadURI(kServer->getURIForPath("/normal").data());
+    test->waitUntilLoadFinished();
+    assertNormalLoadHappened(test->m_loadEvents);
+
+    test->loadURI(kServer->getURIForPath("/normal2").data());
+    test->waitUntilLoadFinished();
+    assertNormalLoadHappened(test->m_loadEvents);
+
+    // Check that load process is the same for pages loaded from history cache.
+    test->goBack();
+    test->waitUntilLoadFinished();
+    assertNormalLoadHappened(test->m_loadEvents);
+
+    test->goForward();
+    test->waitUntilLoadFinished();
+    assertNormalLoadHappened(test->m_loadEvents);
+}
+
 class ViewURITrackingTest: public LoadTrackingTest {
 public:
     MAKE_GLIB_TEST_FIXTURE(ViewURITrackingTest);
@@ -217,7 +237,7 @@
 
     soup_message_set_status(message, SOUP_STATUS_OK);
 
-    if (g_str_equal(path, "/normal"))
+    if (g_str_has_prefix(path, "/normal"))
         soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, responseString, strlen(responseString));
     else if (g_str_equal(path, "/error"))
         soup_message_set_status(message, SOUP_STATUS_CANT_CONNECT);
@@ -248,6 +268,7 @@
     LoadTrackingTest::add("WebKitWebView", "title", testWebViewTitle);
     LoadTrackingTest::add("WebKitWebView", "progress", testLoadProgress);
     LoadTrackingTest::add("WebKitWebView", "reload", testWebViewReload);
+    LoadTrackingTest::add("WebKitWebView", "history-load", testWebViewHistoryLoad);
 
     // This test checks that web view notify::uri signal is correctly emitted
     // and the uri is already updated when loader client signals are emitted.
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to