Title: [137487] trunk
Revision
137487
Author
[email protected]
Date
2012-12-12 11:20:08 -0800 (Wed, 12 Dec 2012)

Log Message

[GTK] Add authentication support to DRT and fix exposed issues in the libsoup backend
https://bugs.webkit.org/show_bug.cgi?id=104285

Reviewed by Gustavo Noronha Silva.

Source/WebCore:

Fix issues in the libsoup networking backend that were causing test
failures.

No new tests. This patch unskips authentication tests.

* platform/network/soup/ResourceHandleSoup.cpp:
(WebCore::isAuthenticationFailureStatusCode): Added this helper to catch authentication status codes
and use it everywhere.
(WebCore::applyAuthenticationToRequest): Use an early return instead of an if-statement
and instead of always using manually specified credentials, apply those found in the session
storage as well. Instead of applying the credentials to firstRequest always, accept the request
as a parameter, so this method can be properly used with redirects.
(WebCore::restartedCallback): Instead of creating the KURL directly from soup_uri_to_string
use soupURIToKURL, which preserves the password from the SoupURI. soup_uri_to_string doesn't
include the password. When calling applyAuthenticationToRequest update the new request. Before
applyAuthenticationToRequest always updated the firstRequest. Do not call willSendRequest for
instances when this method is called for authentication handling. willSendRequest should only
be called for server-side redirects.
(WebCore::createSoupRequestAndMessageForHandle): Use soup_requester_request_uri instead of
soup_requester_request. Request::soupURI properly creates a SoupURI with non-null empty strings
when either the username and password are empty.  A null username or password does not trigger
the URI-embedded credential override in SoupAuthenticationManager within libsoup. This is important
because sometimes either the username or password might empty for a request, but the other
part of the credential should still override the per-session credential storage.
(WebCore::ResourceHandle::start): We don't need to clear the username and password from the
internal data structure any longer. These need to be cleared in the CFNetwork backend because
it prevents the same failed per-request credentials from being used over and over again. In our
case we don't use these members during didReceiveAuthenticationChallenge, so this isn't an issue.
(WebCore::ResourceHandle::didReceiveAuthenticationChallenge): Don't look at the per-request
m_user/m_pass pair here any longer. We use these when initially creating a request, so we don't
want to re-use them if they fail.
* platform/network/soup/ResourceRequest.h:
(ResourceRequest): Rename urlStringForSoup to soupURI.
* platform/network/soup/ResourceRequestSoup.cpp:
(WebCore::ResourceRequest::soupURI): Instead of returning a string for the soup-bound URL
return a SoupURI that properly embeds empty usernames and passwords.

Source/WebKit/gtk:

Add support to DumpRenderTree for running authentication tests. Since the DRT
expects an authentication callback, we add one to DRTSupport to avoid #ifdefs
in platform-independent code for GTK+.

* WebCoreSupport/DumpRenderTreeSupportGtk.cpp:
(DumpRenderTreeSupportGtk::setAuthenticationCallback): Added.
* WebCoreSupport/DumpRenderTreeSupportGtk.h:
(DumpRenderTreeSupportGtk): Add a method to set the authentication callback.
* WebCoreSupport/FrameLoaderClientGtk.cpp:
(WebKit::FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge): When
in DRT mode we need to call the authentication callback instead of popping
up the dialog or ignoring the request.

Tools:

Add support to DumpRenderTree for running authentication tests. Since the DRT
expects an authentication callback, we add one to DRTSupport to avoid #ifdefs
in platform-independent code for GTK+.

* DumpRenderTree/gtk/DumpRenderTree.cpp:
(resetDefaultsToConsistentValues): Reset the authentication password and username.
(authenticationCallback): Added.
(createWebView): Attach the authentiation callback during startup.
* DumpRenderTree/gtk/TestRunnerGtk.cpp:
(soupURIToKURL): soup_uri_to_string does not preserve passwords embedded
in the URL so we add a somewhat messy method of re-adding them when they exist.
It would be nice to use soupURIToKURL here, but it seems we cannot use KURL without
pulling in lots of WebCore code so we use string search and replace.
(TestRunner::queueLoad): Use the new helper.

LayoutTests:

Unskip authentication tests now that authentication support is in
the harness and issues in the libsoup backend are fixed. Also remove
two expected results for tests that now have the same output as
other platforms.

* platform/gtk/TestExpectations:
* platform/gtk/http/tests/misc/401-alternative-content-expected.txt: Removed.
* platform/gtk/http/tests/xmlhttprequest/failed-auth-expected.txt: Removed.

Modified Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (137486 => 137487)


--- trunk/LayoutTests/ChangeLog	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/LayoutTests/ChangeLog	2012-12-12 19:20:08 UTC (rev 137487)
@@ -1,3 +1,19 @@
+2012-12-12  Martin Robinson  <[email protected]>
+
+        [GTK] Add authentication support to DRT and fix exposed issues in the libsoup backend
+        https://bugs.webkit.org/show_bug.cgi?id=104285
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Unskip authentication tests now that authentication support is in
+        the harness and issues in the libsoup backend are fixed. Also remove
+        two expected results for tests that now have the same output as
+        other platforms.
+
+        * platform/gtk/TestExpectations:
+        * platform/gtk/http/tests/misc/401-alternative-content-expected.txt: Removed.
+        * platform/gtk/http/tests/xmlhttprequest/failed-auth-expected.txt: Removed.
+
 2012-12-12  Chris Fleizach  <[email protected]>
 
         AX: aria-busy should be exposed everywhere, not just on live regions

Modified: trunk/LayoutTests/platform/gtk/TestExpectations (137486 => 137487)


--- trunk/LayoutTests/platform/gtk/TestExpectations	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/LayoutTests/platform/gtk/TestExpectations	2012-12-12 19:20:08 UTC (rev 137487)
@@ -890,18 +890,6 @@
 
 webkit.org/b/53986 svg/text/caret-in-svg-text.xhtml [ Failure ]
 
-# No authentication challenge handling
-webkit.org/b/51104 http/tests/loading/authentication-after-redirect-stores-wrong-credentials/authentication-after-redirect-stores-wrong-credentials.html [ Skip ]
-webkit.org/b/51104 http/tests/loading/basic-auth-resend-wrong-credentials.html [ Failure ]
-webkit.org/b/51104 http/tests/loading/basic-credentials-sent-automatically.html [ Failure ]
-webkit.org/b/51104 http/tests/misc/authentication-redirect-1/authentication-sent-to-redirect-cross-origin.html [ Failure ]
-webkit.org/b/51104 http/tests/misc/authentication-redirect-2/authentication-sent-to-redirect-same-origin.html [ Failure ]
-webkit.org/b/51104 http/tests/misc/authentication-redirect-3/authentication-sent-to-redirect-same-origin-with-location-credentials.html [ Failure ]
-webkit.org/b/51104 http/tests/security/401-logout/401-logout.php [ Skip ]
-webkit.org/b/51104 http/tests/xmlhttprequest/basic-auth-nouser.html [ Failure ]
-webkit.org/b/51104 http/tests/xmlhttprequest/basic-auth-nopassword.html [ Failure ]
-webkit.org/b/51104 http/tests/xmlhttprequest/remember-bad-password.html [ Failure ]
-
 # This port doesn't have a global history delegate yet
 Bug(GTK) http/tests/globalhistory [ Failure ]
 

Deleted: trunk/LayoutTests/platform/gtk/http/tests/misc/401-alternative-content-expected.txt (137486 => 137487)


--- trunk/LayoutTests/platform/gtk/http/tests/misc/401-alternative-content-expected.txt	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/LayoutTests/platform/gtk/http/tests/misc/401-alternative-content-expected.txt	2012-12-12 19:20:08 UTC (rev 137487)
@@ -1 +0,0 @@
-PASS

Deleted: trunk/LayoutTests/platform/gtk/http/tests/xmlhttprequest/failed-auth-expected.txt (137486 => 137487)


--- trunk/LayoutTests/platform/gtk/http/tests/xmlhttprequest/failed-auth-expected.txt	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/LayoutTests/platform/gtk/http/tests/xmlhttprequest/failed-auth-expected.txt	2012-12-12 19:20:08 UTC (rev 137487)
@@ -1,6 +0,0 @@
-Test for bug 13075: XMLHttpRequest with failed authentication should set status to 401.
-
-Sync, no credentials: OK
-Sync, incorrect credentials: OK
-Async, no credentials: OK
-Async, incorrect credentials: OK

Modified: trunk/Source/WebCore/ChangeLog (137486 => 137487)


--- trunk/Source/WebCore/ChangeLog	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebCore/ChangeLog	2012-12-12 19:20:08 UTC (rev 137487)
@@ -1,3 +1,47 @@
+2012-12-12  Martin Robinson  <[email protected]>
+
+        [GTK] Add authentication support to DRT and fix exposed issues in the libsoup backend
+        https://bugs.webkit.org/show_bug.cgi?id=104285
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Fix issues in the libsoup networking backend that were causing test
+        failures.
+
+        No new tests. This patch unskips authentication tests.
+
+        * platform/network/soup/ResourceHandleSoup.cpp:
+        (WebCore::isAuthenticationFailureStatusCode): Added this helper to catch authentication status codes
+        and use it everywhere.
+        (WebCore::applyAuthenticationToRequest): Use an early return instead of an if-statement
+        and instead of always using manually specified credentials, apply those found in the session
+        storage as well. Instead of applying the credentials to firstRequest always, accept the request
+        as a parameter, so this method can be properly used with redirects.
+        (WebCore::restartedCallback): Instead of creating the KURL directly from soup_uri_to_string
+        use soupURIToKURL, which preserves the password from the SoupURI. soup_uri_to_string doesn't
+        include the password. When calling applyAuthenticationToRequest update the new request. Before
+        applyAuthenticationToRequest always updated the firstRequest. Do not call willSendRequest for
+        instances when this method is called for authentication handling. willSendRequest should only
+        be called for server-side redirects.
+        (WebCore::createSoupRequestAndMessageForHandle): Use soup_requester_request_uri instead of
+        soup_requester_request. Request::soupURI properly creates a SoupURI with non-null empty strings
+        when either the username and password are empty.  A null username or password does not trigger
+        the URI-embedded credential override in SoupAuthenticationManager within libsoup. This is important
+        because sometimes either the username or password might empty for a request, but the other
+        part of the credential should still override the per-session credential storage.
+        (WebCore::ResourceHandle::start): We don't need to clear the username and password from the
+        internal data structure any longer. These need to be cleared in the CFNetwork backend because
+        it prevents the same failed per-request credentials from being used over and over again. In our
+        case we don't use these members during didReceiveAuthenticationChallenge, so this isn't an issue.
+        (WebCore::ResourceHandle::didReceiveAuthenticationChallenge): Don't look at the per-request
+        m_user/m_pass pair here any longer. We use these when initially creating a request, so we don't
+        want to re-use them if they fail.
+        * platform/network/soup/ResourceRequest.h:
+        (ResourceRequest): Rename urlStringForSoup to soupURI.
+        * platform/network/soup/ResourceRequestSoup.cpp:
+        (WebCore::ResourceRequest::soupURI): Instead of returning a string for the soup-bound URL
+        return a SoupURI that properly embeds empty usernames and passwords.
+
 2012-12-12  Alexey Proskuryakov  <[email protected]>
 
         Make LOG() work in WebProcess and NetworkProcess

Modified: trunk/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp (137486 => 137487)


--- trunk/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp	2012-12-12 19:20:08 UTC (rev 137487)
@@ -47,6 +47,7 @@
 #include "ResourceHandleInternal.h"
 #include "ResourceResponse.h"
 #include "SharedBuffer.h"
+#include "SoupURIUtils.h"
 #include "TextEncoding.h"
 #include <errno.h>
 #include <fcntl.h>
@@ -296,6 +297,11 @@
     return session;
 }
 
+static bool isAuthenticationFailureStatusCode(int httpStatusCode)
+{
+    return httpStatusCode == SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED || httpStatusCode == SOUP_STATUS_UNAUTHORIZED;
+}
+
 static void gotHeadersCallback(SoupMessage* message, gpointer data)
 {
     ResourceHandle* handle = static_cast<ResourceHandle*>(data);
@@ -315,7 +321,7 @@
     // since we are waiting until we know that this authentication succeeded before actually storing.
     // This is because we want to avoid hitting the disk twice (once to add and once to remove) for
     // incorrect credentials or polluting the keychain with invalid credentials.
-    if (message->status_code != 401 && message->status_code < 500 && !d->m_credentialDataToSaveInPersistentStore.credential.isEmpty()) {
+    if (!isAuthenticationFailureStatusCode(message->status_code) && message->status_code < 500 && !d->m_credentialDataToSaveInPersistentStore.credential.isEmpty()) {
         credentialBackingStore().storeCredentialsForChallenge(
             d->m_credentialDataToSaveInPersistentStore.challenge,
             d->m_credentialDataToSaveInPersistentStore.credential);
@@ -330,14 +336,11 @@
     d->m_response = response;
 }
 
-static void applyAuthenticationToRequest(ResourceHandle* handle, bool redirect)
+static void applyAuthenticationToRequest(ResourceHandle* handle, ResourceRequest& request, bool redirect)
 {
     // m_user/m_pass are credentials given manually, for instance, by the arguments passed to XMLHttpRequest.open().
     ResourceHandleInternal* d = handle->getInternal();
-    String user = d->m_user;
-    String password = d->m_pass;
 
-    ResourceRequest& request = d->m_firstRequest;
     if (handle->shouldUseCredentialStorage()) {
         if (d->m_user.isEmpty() && d->m_pass.isEmpty())
             d->m_initialCredential = CredentialStorage::get(request.url());
@@ -350,20 +353,23 @@
         }
     }
 
+    String user = d->m_user;
+    String password = d->m_pass;
     if (!d->m_initialCredential.isEmpty()) {
         user = d->m_initialCredential.user();
         password = d->m_initialCredential.password();
     }
 
+    if (user.isEmpty() && password.isEmpty())
+        return;
+
     // We always put the credentials into the URL. In the CFNetwork-port HTTP family credentials are applied in
     // the didReceiveAuthenticationChallenge callback, but libsoup requires us to use this method to override
     // any previously remembered credentials. It has its own per-session credential storage.
-    if (!user.isEmpty() || !password.isEmpty()) {
-        KURL urlWithCredentials(request.url());
-        urlWithCredentials.setUser(d->m_user);
-        urlWithCredentials.setPass(d->m_pass);
-        request.setURL(urlWithCredentials);
-    }
+    KURL urlWithCredentials(request.url());
+    urlWithCredentials.setUser(user);
+    urlWithCredentials.setPass(password);
+    request.setURL(urlWithCredentials);
 }
 
 // Called each time the message is going to be sent again except the first time.
@@ -377,12 +383,20 @@
     if (d->m_cancelled)
         return;
 
-    GOwnPtr<char> uri(soup_uri_to_string(soup_message_get_uri(message), false));
-    String location = String::fromUTF8(uri.get());
-    KURL newURL = KURL(handle->firstRequest().url(), location);
+    ResourceResponse& redirectResponse = d->m_response;
+#if ENABLE(WEB_TIMING)
+    redirectResponse.setResourceLoadTiming(ResourceLoadTiming::create());
+    redirectResponse.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime();
+#endif
 
+    // WebCore only expects us to call willSendRequest when we are redirecting. soup
+    // fires this signal also when it's handling authentication challenges, so in that
+    // case we should not willSendRequest.
+    if (isAuthenticationFailureStatusCode(redirectResponse.httpStatusCode()))
+        return;
+
     ResourceRequest request = handle->firstRequest();
-    request.setURL(newURL);
+    request.setURL(KURL(handle->firstRequest().url(), soupURIToKURL(soup_message_get_uri(message))));
     request.setHTTPMethod(message->method);
 
     // Should not set Referer after a redirect from a secure resource to non-secure one.
@@ -396,7 +410,6 @@
     d->m_pass = url.pass();
     request.removeCredentials();
 
-    ResourceResponse& redirectResponse = d->m_response;
     if (!protocolHostAndPortAreEqual(request.url(), redirectResponse.url())) {
         // If the network layer carries over authentication headers from the original request
         // in a cross-origin redirect, we want to clear those headers here. 
@@ -406,10 +419,10 @@
         // TODO: We are losing any username and password specified in the redirect URL, as this is the 
         // same behavior as the CFNet port. We should investigate if this is really what we want.
     } else
-        applyAuthenticationToRequest(handle, true);
+        applyAuthenticationToRequest(handle, request, true);
 
     // Per-request authentication is handled via the URI-embedded username/password.
-    GOwnPtr<SoupURI> newSoupURI(soup_uri_new(request.urlStringForSoup().utf8().data()));
+    GOwnPtr<SoupURI> newSoupURI(request.soupURI());
     soup_message_set_uri(message, newSoupURI.get());
 
     if (d->client())
@@ -418,11 +431,6 @@
     if (d->m_cancelled)
         return;
 
-#if ENABLE(WEB_TIMING)
-    redirectResponse.setResourceLoadTiming(ResourceLoadTiming::create());
-    redirectResponse.resourceLoadTiming()->requestTime = monotonicallyIncreasingTime();
-#endif
-
     // Update the first party in case the base URL changed with the redirect
     String firstPartyString = request.firstPartyForCookies().string();
     if (!firstPartyString.isEmpty()) {
@@ -883,7 +891,8 @@
     GOwnPtr<GError> error;
     ResourceRequest& request = handle->firstRequest();
 
-    d->m_soupRequest = adoptGRef(soup_requester_request(requester, request.urlStringForSoup().utf8().data(), &error.outPtr()));
+    GOwnPtr<SoupURI> soupURI(request.soupURI());
+    d->m_soupRequest = adoptGRef(soup_requester_request_uri(requester, soupURI.get(), &error.outPtr()));
     if (error) {
         d->m_soupRequest.clear();
         return false;
@@ -921,10 +930,7 @@
         return true;
     }
 
-    applyAuthenticationToRequest(this, false);
-    // The CFNet backend clears these, so we do as well.
-    d->m_user = String();
-    d->m_pass = String();
+    applyAuthenticationToRequest(this, firstRequest(), false);
 
     if (!createSoupRequestAndMessageForHandle(this, isHTTPFamilyRequest)) {
         this->scheduleFailure(InvalidURLFailure); // Error must not be reported immediately
@@ -1022,17 +1028,8 @@
 {
     ASSERT(d->m_currentWebChallenge.isNull());
 
-    bool useCredentialStorage = shouldUseCredentialStorage();
-    if (!d->m_user.isNull() && !d->m_pass.isNull()) {
-        Credential credential = Credential(d->m_user, d->m_pass, CredentialPersistenceForSession);
-        if (useCredentialStorage)
-            CredentialStorage::set(credential, challenge.protectionSpace(), challenge.failureResponse().url());
-        soup_auth_authenticate(challenge.soupAuth(), credential.user().utf8().data(), credential.password().utf8().data());
-
-        return;
-    }
-
     // FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly.
+    bool useCredentialStorage = shouldUseCredentialStorage();
     if (useCredentialStorage) {
         if (!d->m_initialCredential.isEmpty() || challenge.previousFailureCount()) {
             // The stored credential wasn't accepted, stop using it. There is a race condition
@@ -1047,7 +1044,7 @@
                 ASSERT(credential.persistence() == CredentialPersistenceNone);
 
                 // Store the credential back, possibly adding it as a default for this directory.
-                if (challenge.failureResponse().httpStatusCode() == 401)
+                if (isAuthenticationFailureStatusCode(challenge.failureResponse().httpStatusCode()))
                     CredentialStorage::set(credential, challenge.protectionSpace(), challenge.failureResponse().url());
 
                 soup_auth_authenticate(challenge.soupAuth(), credential.user().utf8().data(), credential.password().utf8().data());

Modified: trunk/Source/WebCore/platform/network/soup/ResourceRequest.h (137486 => 137487)


--- trunk/Source/WebCore/platform/network/soup/ResourceRequest.h	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebCore/platform/network/soup/ResourceRequest.h	2012-12-12 19:20:08 UTC (rev 137487)
@@ -74,7 +74,7 @@
         SoupMessageFlags soupMessageFlags() const { return m_soupFlags; }
         void setSoupMessageFlags(SoupMessageFlags soupFlags) { m_soupFlags = soupFlags; }
 
-        String urlStringForSoup() const;
+        SoupURI* soupURI() const;
 
     private:
         friend class ResourceRequestBase;

Modified: trunk/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp (137486 => 137487)


--- trunk/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp	2012-12-12 19:20:08 UTC (rev 137487)
@@ -119,7 +119,7 @@
     return 10000;
 }
 
-String ResourceRequest::urlStringForSoup() const
+SoupURI* ResourceRequest::soupURI() const
 {
     // WebKit does not support fragment identifiers in data URLs, but soup does.
     // Before passing the URL to soup, we should make sure to urlencode any '#'
@@ -128,12 +128,22 @@
     if (m_url.protocolIsData()) {
         String urlString = m_url.string();
         urlString.replace("#", "%23");
-        return urlString;
+        return soup_uri_new(urlString.utf8().data());
     }
 
     KURL url = ""
     url.removeFragmentIdentifier();
-    return url.string();
+    SoupURI* uri = soup_uri_new(url.string().utf8().data());
+
+    // Versions of libsoup prior to 2.42 have a soup_uri_new that will convert empty passwords that are not
+    // prefixed by a colon into null. Some parts of soup like the SoupAuthenticationManager will only be active
+    // when both the username and password are non-null. When we have credentials, empty usernames and passwords
+    // should be empty strings instead of null.
+    if (!url.user().isEmpty() || !url.pass().isEmpty()) {
+        soup_uri_set_user(uri, url.user().utf8().data());
+        soup_uri_set_password(uri, url.pass().utf8().data());
+    }
+    return uri;
 }
 
 }

Modified: trunk/Source/WebKit/gtk/ChangeLog (137486 => 137487)


--- trunk/Source/WebKit/gtk/ChangeLog	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebKit/gtk/ChangeLog	2012-12-12 19:20:08 UTC (rev 137487)
@@ -1,3 +1,23 @@
+2012-12-12  Martin Robinson  <[email protected]>
+
+        [GTK] Add authentication support to DRT and fix exposed issues in the libsoup backend
+        https://bugs.webkit.org/show_bug.cgi?id=104285
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Add support to DumpRenderTree for running authentication tests. Since the DRT
+        expects an authentication callback, we add one to DRTSupport to avoid #ifdefs
+        in platform-independent code for GTK+.
+
+        * WebCoreSupport/DumpRenderTreeSupportGtk.cpp:
+        (DumpRenderTreeSupportGtk::setAuthenticationCallback): Added.
+        * WebCoreSupport/DumpRenderTreeSupportGtk.h:
+        (DumpRenderTreeSupportGtk): Add a method to set the authentication callback.
+        * WebCoreSupport/FrameLoaderClientGtk.cpp:
+        (WebKit::FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge): When
+        in DRT mode we need to call the authentication callback instead of popping
+        up the dialog or ignoring the request.
+
 2012-12-12  Alexey Proskuryakov  <[email protected]>
 
         Make LOG() work in WebProcess and NetworkProcess

Modified: trunk/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp (137486 => 137487)


--- trunk/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.cpp	2012-12-12 19:20:08 UTC (rev 137487)
@@ -85,6 +85,7 @@
 bool DumpRenderTreeSupportGtk::s_linksIncludedInTabChain = true;
 bool DumpRenderTreeSupportGtk::s_selectTrailingWhitespaceEnabled = false;
 DumpRenderTreeSupportGtk::FrameLoadEventCallback DumpRenderTreeSupportGtk::s_frameLoadEventCallback = 0;
+DumpRenderTreeSupportGtk::AuthenticationCallback DumpRenderTreeSupportGtk::s_authenticationCallback = 0;
 
 DumpRenderTreeSupportGtk::DumpRenderTreeSupportGtk()
 {
@@ -841,3 +842,8 @@
 {
     s_frameLoadEventCallback = frameLoadEventCallback;
 }
+
+void DumpRenderTreeSupportGtk::setAuthenticationCallback(AuthenticationCallback authenticationCallback)
+{
+    s_authenticationCallback = authenticationCallback;
+}

Modified: trunk/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h (137486 => 137487)


--- trunk/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebKit/gtk/WebCoreSupport/DumpRenderTreeSupportGtk.h	2012-12-12 19:20:08 UTC (rev 137487)
@@ -146,6 +146,10 @@
     static void setFrameLoadEventCallback(FrameLoadEventCallback);
     static FrameLoadEventCallback s_frameLoadEventCallback;
 
+    typedef bool (*AuthenticationCallback) (CString& username, CString& password);
+    static void setAuthenticationCallback(AuthenticationCallback);
+    static AuthenticationCallback s_authenticationCallback;
+
 private:
     static bool s_drtRun;
     static bool s_linksIncludedInTabChain;

Modified: trunk/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp (137486 => 137487)


--- trunk/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Source/WebKit/gtk/WebCoreSupport/FrameLoaderClientGtk.cpp	2012-12-12 19:20:08 UTC (rev 137487)
@@ -193,7 +193,14 @@
 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge& challenge)
 {
     if (DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) {
-        challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
+        CString username;
+        CString password;
+        if (!DumpRenderTreeSupportGtk::s_authenticationCallback || !DumpRenderTreeSupportGtk::s_authenticationCallback(username, password)) {
+            challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
+            return;
+        }
+
+        challenge.authenticationClient()->receivedCredential(challenge, Credential(String::fromUTF8(username.data()), String::fromUTF8(password.data()), CredentialPersistenceForSession));
         return;
     }
 

Modified: trunk/Tools/ChangeLog (137486 => 137487)


--- trunk/Tools/ChangeLog	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Tools/ChangeLog	2012-12-12 19:20:08 UTC (rev 137487)
@@ -1,3 +1,25 @@
+2012-12-12  Martin Robinson  <[email protected]>
+
+        [GTK] Add authentication support to DRT and fix exposed issues in the libsoup backend
+        https://bugs.webkit.org/show_bug.cgi?id=104285
+
+        Reviewed by Gustavo Noronha Silva.
+
+        Add support to DumpRenderTree for running authentication tests. Since the DRT
+        expects an authentication callback, we add one to DRTSupport to avoid #ifdefs
+        in platform-independent code for GTK+.
+
+        * DumpRenderTree/gtk/DumpRenderTree.cpp:
+        (resetDefaultsToConsistentValues): Reset the authentication password and username.
+        (authenticationCallback): Added.
+        (createWebView): Attach the authentiation callback during startup.
+        * DumpRenderTree/gtk/TestRunnerGtk.cpp:
+        (soupURIToKURL): soup_uri_to_string does not preserve passwords embedded
+        in the URL so we add a somewhat messy method of re-adding them when they exist.
+        It would be nice to use soupURIToKURL here, but it seems we cannot use KURL without
+        pulling in lots of WebCore code so we use string search and replace.
+        (TestRunner::queueLoad): Use the new helper.
+
 2012-12-12  Dirk Pranke  <[email protected]>
 
         garden-o-matic should prefer efl/ over efl-wk1/ and efl-wk2/ when rebaselining

Modified: trunk/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp (137486 => 137487)


--- trunk/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Tools/DumpRenderTree/gtk/DumpRenderTree.cpp	2012-12-12 19:20:08 UTC (rev 137487)
@@ -520,6 +520,12 @@
     DumpRenderTreeSupportGtk::setExperimentalContentSecurityPolicyFeaturesEnabled(true);
     DumpRenderTreeSupportGtk::setShadowDOMEnabled(true);
     DumpRenderTreeSupportGtk::setStyleScopedEnabled(true);
+
+    if (gTestRunner) {
+        gTestRunner->setAuthenticationPassword("");
+        gTestRunner->setAuthenticationUsername("");
+        gTestRunner->setHandlesAuthenticationChallenges(false);
+    }
 }
 
 static bool useLongRunningServerMode(int argc, char *argv[])
@@ -1362,6 +1368,19 @@
     }
 }
 
+static bool authenticationCallback(CString& username, CString& password)
+{
+    if (!gTestRunner->handlesAuthenticationChallenges()) {
+        printf("<unknown> - didReceiveAuthenticationChallenge - Simulating cancelled authentication sheet\n");
+        return false;
+    }
+
+    username = gTestRunner->authenticationUsername().c_str();
+    password = gTestRunner->authenticationPassword().c_str();
+    printf("<unknown> - didReceiveAuthenticationChallenge - Responding with %s:%s\n", username.data(), password.data());
+    return true;
+}
+
 static WebKitWebView* createWebView()
 {
     // It is important to declare DRT is running early so when creating
@@ -1369,6 +1388,7 @@
     DumpRenderTreeSupportGtk::setDumpRenderTreeModeEnabled(true);
 
     DumpRenderTreeSupportGtk::setFrameLoadEventCallback(frameLoadEventCallback);
+    DumpRenderTreeSupportGtk::setAuthenticationCallback(authenticationCallback);
 
     WebKitWebView* view = WEBKIT_WEB_VIEW(self_scrolling_webkit_web_view_new());
 

Modified: trunk/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp (137486 => 137487)


--- trunk/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp	2012-12-12 19:07:30 UTC (rev 137486)
+++ trunk/Tools/DumpRenderTree/gtk/TestRunnerGtk.cpp	2012-12-12 19:20:08 UTC (rev 137487)
@@ -48,6 +48,7 @@
 #include <libsoup/soup.h>
 #include <webkit/webkit.h>
 #include <wtf/gobject/GOwnPtr.h>
+#include <wtf/text/WTFString.h>
 
 extern "C" {
 void webkit_web_inspector_execute_script(WebKitWebInspector* inspector, long callId, const gchar* script);
@@ -157,26 +158,43 @@
     return JSStringCreateWithUTF8CString(testURI.get());
 }
 
+static CString soupURIToStringPreservingPassword(SoupURI* soupURI)
+{
+    if (!soupURI->password) {
+        GOwnPtr<char> uriString(soup_uri_to_string(soupURI, FALSE));
+        return uriString.get();
+    }
+
+    // soup_uri_to_string does not insert the password into the string, so we need to create the
+    // URI string and then reinsert any credentials that were present in the SoupURI. All tests that
+    // use URL-embedded credentials use HTTP, so it's safe here.
+    GOwnPtr<char> password(soupURI->password);
+    GOwnPtr<char> user(soupURI->user);
+    soupURI->password = 0;
+    soupURI->user = 0;
+
+    GOwnPtr<char> uriString(soup_uri_to_string(soupURI, FALSE));
+    String absoluteURIWithoutCredentialString = String::fromUTF8(uriString.get());
+    String protocolAndCredential = String::format("http://%s:%s@", user ? user.get() : "", password.get());
+    return absoluteURIWithoutCredentialString.replace("http://", protocolAndCredential).utf8();
+}
+
 void TestRunner::queueLoad(JSStringRef url, JSStringRef target)
 {
-    gchar* relativeURL = JSStringCopyUTF8CString(url);
+    GOwnPtr<gchar> relativeURL(JSStringCopyUTF8CString(url));
     SoupURI* baseURI = soup_uri_new(webkit_web_frame_get_uri(mainFrame));
-
-    SoupURI* absoluteURI = soup_uri_new_with_base(baseURI, relativeURL);
+    SoupURI* absoluteURI = soup_uri_new_with_base(baseURI, relativeURL.get());
     soup_uri_free(baseURI);
-    g_free(relativeURL);
 
-    gchar* absoluteCString;
-    if (absoluteURI) {
-        absoluteCString = soup_uri_to_string(absoluteURI, FALSE);
-        soup_uri_free(absoluteURI);
-    } else
-        absoluteCString = JSStringCopyUTF8CString(url);
+    if (!absoluteURI) {
+        WorkQueue::shared()->queue(new LoadItem(url, target));
+        return;
+    }
 
-    JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString(absoluteCString));
-    g_free(absoluteCString);
-
+    CString absoluteURIString = soupURIToStringPreservingPassword(absoluteURI);
+    JSRetainPtr<JSStringRef> absoluteURL(Adopt, JSStringCreateWithUTF8CString(absoluteURIString.data()));
     WorkQueue::shared()->queue(new LoadItem(absoluteURL.get(), target));
+    soup_uri_free(absoluteURI);
 }
 
 void TestRunner::setAcceptsEditing(bool acceptsEditing)
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to