Skip to content

Commit

Permalink
Merge r155347 - [GTK] Cancel the current active WebKitAuthenticationR…
Browse files Browse the repository at this point in the history
…equest on load failed

https://bugs.webkit.org/show_bug.cgi?id=120350

Patch by Anton Obzhirov <a.obzhirov@samsung.com> on 2013-09-09
Reviewed by Carlos Garcia Campos.

The default dialog does not get closed and the authentication is not cancelled
if loading fails or is stopped on a page which requires HTTP authentication.

This patch cancels the authentication request on load failed
and adds new authentication cancelled signal in WebKitAuthenticationRequest
to allow the application handling of authentication UI.

* UIProcess/API/gtk/WebKitAuthenticationDialog.cpp:
(authenticationCancelled):
(webkitAuthenticationDialogInitialize):
(webkitAuthenticationDialogDispose):
(webkitAuthenticationDialogNew):
* UIProcess/API/gtk/WebKitAuthenticationDialog.h:
* UIProcess/API/gtk/WebKitAuthenticationRequest.cpp:
(webkit_authentication_request_class_init):
(webkit_authentication_request_cancel):
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewAuthenticate):
(webkitWebViewLoadFailed):
(webkitWebViewHandleAuthenticationChallenge):
(webkitWebViewCancelAuthenticationRequest):
* UIProcess/API/gtk/tests/TestWebKitWebView.cpp:
(testWebViewAuthenticationLoadCancelled):
(beforeAll):
  • Loading branch information
Anton Obzhirov authored and carlosgcampos committed Sep 9, 2013
1 parent 65adf30 commit 21db3d9
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 25 deletions.
32 changes: 32 additions & 0 deletions Source/WebKit2/ChangeLog
@@ -1,3 +1,35 @@
2013-09-09 Anton Obzhirov <a.obzhirov@samsung.com>

[GTK] Cancel the current active WebKitAuthenticationRequest on load failed
https://bugs.webkit.org/show_bug.cgi?id=120350

Reviewed by Carlos Garcia Campos.

The default dialog does not get closed and the authentication is not cancelled
if loading fails or is stopped on a page which requires HTTP authentication.

This patch cancels the authentication request on load failed
and adds new authentication cancelled signal in WebKitAuthenticationRequest
to allow the application handling of authentication UI.

* UIProcess/API/gtk/WebKitAuthenticationDialog.cpp:
(authenticationCancelled):
(webkitAuthenticationDialogInitialize):
(webkitAuthenticationDialogDispose):
(webkitAuthenticationDialogNew):
* UIProcess/API/gtk/WebKitAuthenticationDialog.h:
* UIProcess/API/gtk/WebKitAuthenticationRequest.cpp:
(webkit_authentication_request_class_init):
(webkit_authentication_request_cancel):
* UIProcess/API/gtk/WebKitWebView.cpp:
(webkitWebViewAuthenticate):
(webkitWebViewLoadFailed):
(webkitWebViewHandleAuthenticationChallenge):
(webkitWebViewCancelAuthenticationRequest):
* UIProcess/API/gtk/tests/TestWebKitWebView.cpp:
(testWebViewAuthenticationLoadCancelled):
(beforeAll):

2013-09-05 Alberto Garcia <berto@igalia.com>

[WK2] [GTK] Remove the test to disable AC under Wayland from WebKitWebViewGroup
Expand Down
21 changes: 9 additions & 12 deletions Source/WebKit2/UIProcess/API/gtk/WebKitAuthenticationDialog.cpp
Expand Up @@ -32,9 +32,8 @@ struct _WebKitAuthenticationDialogPrivate {
GRefPtr<WebKitAuthenticationRequest> request;
GtkWidget* authWidget;
GtkWidget* defaultButton;
unsigned long loadFailedEventID;
unsigned long authenticationCancelledID;
GRefPtr<GtkStyleContext> styleContext;
WebKitWebView* webView;
};

WEBKIT_DEFINE_TYPE(WebKitAuthenticationDialog, webkit_authentication_dialog, GTK_TYPE_EVENT_BOX)
Expand All @@ -54,13 +53,12 @@ static void cancelButtonClicked(GtkButton*, WebKitAuthenticationDialog* authDial
gtk_widget_destroy(GTK_WIDGET(authDialog));
}

static void pageLoadFailed(WebKitWebView*, WebKitLoadEvent, const char*, GError*, WebKitAuthenticationDialog* authDialog)
static void authenticationCancelled(WebKitAuthenticationRequest*, WebKitAuthenticationDialog* authDialog)
{
webkit_authentication_request_cancel(authDialog->priv->request.get());
gtk_widget_destroy(GTK_WIDGET(authDialog));
}

static void webkitAuthenticationDialogInitialize(WebKitAuthenticationDialog* authDialog, CredentialStorageMode credentialStorageMode, WebKitWebView* webView)
static void webkitAuthenticationDialogInitialize(WebKitAuthenticationDialog* authDialog, CredentialStorageMode credentialStorageMode)
{
GtkWidget* frame = gtk_frame_new(0);
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
Expand Down Expand Up @@ -98,8 +96,7 @@ static void webkitAuthenticationDialogInitialize(WebKitAuthenticationDialog* aut
gtk_container_add(GTK_CONTAINER(authDialog), frame);
gtk_widget_show(frame);

authDialog->priv->webView = webView;
authDialog->priv->loadFailedEventID = g_signal_connect(webView, "load-failed", G_CALLBACK(pageLoadFailed), authDialog);
authDialog->priv->authenticationCancelledID = g_signal_connect(authDialog->priv->request.get(), "cancelled", G_CALLBACK(authenticationCancelled), authDialog);
}

static gboolean webkitAuthenticationDialogDraw(GtkWidget* widget, cairo_t* cr)
Expand Down Expand Up @@ -139,9 +136,9 @@ static void webkitAuthenticationDialogConstructed(GObject* object)
static void webkitAuthenticationDialogDispose(GObject* object)
{
WebKitAuthenticationDialogPrivate* priv = WEBKIT_AUTHENTICATION_DIALOG(object)->priv;
if (priv->loadFailedEventID) {
g_signal_handler_disconnect(priv->webView, priv->loadFailedEventID);
priv->loadFailedEventID = 0;
if (priv->authenticationCancelledID) {
g_signal_handler_disconnect(priv->request.get(), priv->authenticationCancelledID);
priv->authenticationCancelledID = 0;
}

G_OBJECT_CLASS(webkit_authentication_dialog_parent_class)->dispose(object);
Expand All @@ -158,10 +155,10 @@ static void webkit_authentication_dialog_class_init(WebKitAuthenticationDialogCl
widgetClass->map = webkitAuthenticationDialogMap;
}

GtkWidget* webkitAuthenticationDialogNew(WebKitAuthenticationRequest* request, CredentialStorageMode mode, WebKitWebView* webView)
GtkWidget* webkitAuthenticationDialogNew(WebKitAuthenticationRequest* request, CredentialStorageMode mode)
{
WebKitAuthenticationDialog* authDialog = WEBKIT_AUTHENTICATION_DIALOG(g_object_new(WEBKIT_TYPE_AUTHENTICATION_DIALOG, NULL));
authDialog->priv->request = request;
webkitAuthenticationDialogInitialize(authDialog, mode, webView);
webkitAuthenticationDialogInitialize(authDialog, mode);
return GTK_WIDGET(authDialog);
}
Expand Up @@ -49,7 +49,7 @@ struct _WebKitAuthenticationDialogClass {
};

GType webkit_authentication_dialog_get_type();
GtkWidget* webkitAuthenticationDialogNew(WebKitAuthenticationRequest*, CredentialStorageMode, WebKitWebView*);
GtkWidget* webkitAuthenticationDialogNew(WebKitAuthenticationRequest*, CredentialStorageMode);

G_END_DECLS

Expand Down
28 changes: 28 additions & 0 deletions Source/WebKit2/UIProcess/API/gtk/WebKitAuthenticationRequest.cpp
Expand Up @@ -51,6 +51,12 @@ using namespace WebCore;
* WebKitAuthenticationRequest object.
*/

enum {
CANCELLED,

LAST_SIGNAL
};

struct _WebKitAuthenticationRequestPrivate {
RefPtr<AuthenticationChallengeProxy> authenticationChallenge;
bool privateBrowsingEnabled;
Expand All @@ -59,6 +65,8 @@ struct _WebKitAuthenticationRequestPrivate {
CString realm;
};

static guint signals[LAST_SIGNAL] = { 0, };

COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_AUTHENTICATION_SCHEME_DEFAULT, ProtectionSpaceAuthenticationSchemeDefault);
COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_AUTHENTICATION_SCHEME_HTTP_BASIC, ProtectionSpaceAuthenticationSchemeHTTPBasic);
COMPILE_ASSERT_MATCHING_ENUM(WEBKIT_AUTHENTICATION_SCHEME_HTTP_DIGEST, ProtectionSpaceAuthenticationSchemeHTTPDigest);
Expand Down Expand Up @@ -86,6 +94,24 @@ static void webkit_authentication_request_class_init(WebKitAuthenticationRequest
{
GObjectClass* objectClass = G_OBJECT_CLASS(requestClass);
objectClass->dispose = webkitAuthenticationRequestDispose;

/**
* WebKitAuthenticationRequest::cancelled:
* @request: the #WebKitAuthenticationRequest
*
* This signal is emitted when the user authentication request is
* cancelled. It allows the application to dismiss its authentication
* dialog in case of page load failure for example.
*
* Since: 2.2
*/
signals[CANCELLED] =
g_signal_new("cancelled",
G_TYPE_FROM_CLASS(objectClass),
G_SIGNAL_RUN_LAST,
0, 0, 0,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}

WebKitAuthenticationRequest* webkitAuthenticationRequestCreate(AuthenticationChallengeProxy* authenticationChallenge, bool privateBrowsingEnabled)
Expand Down Expand Up @@ -288,4 +314,6 @@ void webkit_authentication_request_cancel(WebKitAuthenticationRequest* request)
g_return_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request));

request->priv->authenticationChallenge->listener()->cancel();

g_signal_emit(request, signals[CANCELLED], 0);
}
23 changes: 18 additions & 5 deletions Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
Expand Up @@ -190,6 +190,7 @@ struct _WebKitWebViewPrivate {
unsigned long faviconChangedHandlerID;

SnapshotResultsMap snapshotResultsMap;
GRefPtr<WebKitAuthenticationRequest> authenticationRequest;
};

static guint signals[LAST_SIGNAL] = { 0, };
Expand Down Expand Up @@ -437,7 +438,7 @@ static void webkitWebViewDisconnectFaviconDatabaseSignalHandlers(WebKitWebView*
static gboolean webkitWebViewAuthenticate(WebKitWebView* webView, WebKitAuthenticationRequest* request)
{
CredentialStorageMode credentialStorageMode = webkit_authentication_request_can_save_credentials(request) ? AllowPersistentStorage : DisallowPersistentStorage;
webkitWebViewBaseAddAuthenticationDialog(WEBKIT_WEB_VIEW_BASE(webView), webkitAuthenticationDialogNew(request, credentialStorageMode, webView));
webkitWebViewBaseAddAuthenticationDialog(WEBKIT_WEB_VIEW_BASE(webView), webkitAuthenticationDialogNew(request, credentialStorageMode));

return TRUE;
}
Expand Down Expand Up @@ -1430,15 +1431,24 @@ static void webkitWebViewSetIsLoading(WebKitWebView* webView, bool isLoading)
g_object_thaw_notify(G_OBJECT(webView));
}

static void webkitWebViewCancelAuthenticationRequest(WebKitWebView* webView)
{
if (!webView->priv->authenticationRequest)
return;

webkit_authentication_request_cancel(webView->priv->authenticationRequest.get());
webView->priv->authenticationRequest.clear();
}

static void webkitWebViewEmitLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
{
if (loadEvent == WEBKIT_LOAD_STARTED) {
webkitWebViewSetIsLoading(webView, true);
webkitWebViewWatchForChangesInFavicon(webView);
webkitWebViewBaseCancelAuthenticationDialog(WEBKIT_WEB_VIEW_BASE(webView));
webkitWebViewCancelAuthenticationRequest(webView);
} else if (loadEvent == WEBKIT_LOAD_FINISHED) {
webkitWebViewSetIsLoading(webView, false);
webView->priv->waitingForMainResource = false;
webkitWebViewCancelAuthenticationRequest(webView);
webkitWebViewDisconnectMainResourceResponseChangedSignalHandler(webView);
} else
webkitWebViewUpdateURI(webView);
Expand Down Expand Up @@ -1492,6 +1502,8 @@ void webkitWebViewLoadChanged(WebKitWebView* webView, WebKitLoadEvent loadEvent)
void webkitWebViewLoadFailed(WebKitWebView* webView, WebKitLoadEvent loadEvent, const char* failingURI, GError *error)
{
webkitWebViewSetIsLoading(webView, false);
webkitWebViewCancelAuthenticationRequest(webView);

gboolean returnValue;
g_signal_emit(webView, signals[LOAD_FAILED], 0, loadEvent, failingURI, error, &returnValue);
g_signal_emit(webView, signals[LOAD_CHANGED], 0, WEBKIT_LOAD_FINISHED);
Expand All @@ -1500,6 +1512,7 @@ void webkitWebViewLoadFailed(WebKitWebView* webView, WebKitLoadEvent loadEvent,
void webkitWebViewLoadFailedWithTLSErrors(WebKitWebView* webView, const char* failingURI, GError *error, GTlsCertificateFlags tlsErrors, GTlsCertificate* certificate)
{
webkitWebViewSetIsLoading(webView, false);
webkitWebViewCancelAuthenticationRequest(webView);

WebKitTLSErrorsPolicy tlsErrorsPolicy = webkit_web_context_get_tls_errors_policy(webView->priv->context);
if (tlsErrorsPolicy == WEBKIT_TLS_ERRORS_POLICY_FAIL) {
Expand Down Expand Up @@ -1786,9 +1799,9 @@ void webkitWebViewSubmitFormRequest(WebKitWebView* webView, WebKitFormSubmission
void webkitWebViewHandleAuthenticationChallenge(WebKitWebView* webView, AuthenticationChallengeProxy* authenticationChallenge)
{
gboolean privateBrowsingEnabled = webkit_settings_get_enable_private_browsing(webkit_web_view_get_settings(webView));
GRefPtr<WebKitAuthenticationRequest> request = adoptGRef(webkitAuthenticationRequestCreate(authenticationChallenge, privateBrowsingEnabled));
webView->priv->authenticationRequest = adoptGRef(webkitAuthenticationRequestCreate(authenticationChallenge, privateBrowsingEnabled));
gboolean returnValue;
g_signal_emit(webView, signals[AUTHENTICATE], 0, request.get(), &returnValue);
g_signal_emit(webView, signals[AUTHENTICATE], 0, webView->priv->authenticationRequest.get(), &returnValue);
}

void webkitWebViewInsecureContentDetected(WebKitWebView* webView, WebKitInsecureContentEvent type)
Expand Down
7 changes: 0 additions & 7 deletions Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
Expand Up @@ -302,13 +302,6 @@ void webkitWebViewBaseAddAuthenticationDialog(WebKitWebViewBase* webViewBase, Gt
gtk_widget_queue_draw(GTK_WIDGET(webViewBase));
}

void webkitWebViewBaseCancelAuthenticationDialog(WebKitWebViewBase* webViewBase)
{
WebKitWebViewBasePrivate* priv = webViewBase->priv;
if (priv->authenticationDialog)
gtk_widget_destroy(priv->authenticationDialog);
}

void webkitWebViewBaseAddWebInspector(WebKitWebViewBase* webViewBase, GtkWidget* inspector)
{
webViewBase->priv->inspectorView = inspector;
Expand Down
27 changes: 27 additions & 0 deletions Source/WebKit2/UIProcess/API/gtk/tests/TestWebKitWebView.cpp
Expand Up @@ -1248,20 +1248,28 @@ class AuthenticationTest: public LoadTrackingTest {
}

static int authenticationRetries;
static bool authenticationCancelledReceived;

void loadURI(const char* uri)
{
// Reset the retry count of the fake server when a page is loaded.
authenticationRetries = 0;
authenticationCancelledReceived = false;
LoadTrackingTest::loadURI(uri);
}

static gboolean runAuthenticationCallback(WebKitWebView*, WebKitAuthenticationRequest* request, AuthenticationTest* test)
{
g_signal_connect(request, "cancelled", G_CALLBACK(authenticationCancelledCallback), test);
test->runAuthentication(request);
return TRUE;
}

static void authenticationCancelledCallback(WebKitAuthenticationRequest*, AuthenticationTest*)
{
authenticationCancelledReceived = true;
}

void runAuthentication(WebKitAuthenticationRequest* request)
{
assertObjectIsDeletedWhenTestFinishes(G_OBJECT(request));
Expand All @@ -1280,6 +1288,7 @@ class AuthenticationTest: public LoadTrackingTest {
};

int AuthenticationTest::authenticationRetries = 0;
bool AuthenticationTest::authenticationCancelledReceived = false;

static const char authTestUsername[] = "username";
static const char authTestPassword[] = "password";
Expand Down Expand Up @@ -1325,6 +1334,23 @@ static void testWebViewAuthenticationCancel(AuthenticationTest* test, gconstpoin
g_assert_error(test->m_error.get(), WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED);
}

static void testWebViewAuthenticationLoadCancelled(AuthenticationTest* test, gconstpointer)
{
test->loadURI(kServer->getURIForPath("/auth-test.html").data());
test->waitForAuthenticationRequest();
webkit_web_view_stop_loading(test->m_webView);
// Expect empty page.
test->waitUntilLoadFinished();
g_assert(test->authenticationCancelledReceived);

g_assert_cmpint(test->m_loadEvents.size(), ==, 3);
g_assert_cmpint(test->m_loadEvents[0], ==, LoadTrackingTest::ProvisionalLoadStarted);
g_assert_cmpint(test->m_loadEvents[1], ==, LoadTrackingTest::ProvisionalLoadFailed);
g_assert_cmpint(test->m_loadEvents[2], ==, LoadTrackingTest::LoadFinished);

g_assert_error(test->m_error.get(), WEBKIT_NETWORK_ERROR, WEBKIT_NETWORK_ERROR_CANCELLED);
}

static void testWebViewAuthenticationFailure(AuthenticationTest* test, gconstpointer)
{
// Test authentication failures.
Expand Down Expand Up @@ -1474,6 +1500,7 @@ void beforeAll()
WebViewTest::add("WebKitWebView", "page-visibility", testWebViewPageVisibility);
AuthenticationTest::add("WebKitWebView", "authentication-request", testWebViewAuthenticationRequest);
AuthenticationTest::add("WebKitWebView", "authentication-cancel", testWebViewAuthenticationCancel);
AuthenticationTest::add("WebKitWebView", "authentication-load-cancelled", testWebViewAuthenticationLoadCancelled);
AuthenticationTest::add("WebKitWebView", "authentication-failure", testWebViewAuthenticationFailure);
AuthenticationTest::add("WebKitWebView", "authentication-no-credential", testWebViewAuthenticationNoCredential);
AuthenticationTest::add("WebKitWebView", "authentication-storage", testWebViewAuthenticationStorage);
Expand Down

0 comments on commit 21db3d9

Please sign in to comment.