WebKitAuthenticationRequest.cpp [plain text]
#include "config.h"
#include "WebKitAuthenticationRequest.h"
#include "AuthenticationChallengeDisposition.h"
#include "AuthenticationDecisionListener.h"
#include "WebCredential.h"
#include "WebKitAuthenticationRequestPrivate.h"
#include "WebKitCredentialPrivate.h"
#include "WebKitSecurityOriginPrivate.h"
#include "WebProtectionSpace.h"
#include <WebCore/AuthenticationChallenge.h>
#include <WebCore/ProtectionSpace.h>
#include <glib/gi18n-lib.h>
#include <wtf/glib/WTFGType.h>
#include <wtf/text/CString.h>
using namespace WebKit;
using namespace WebCore;
enum {
AUTHENTICATED,
CANCELLED,
LAST_SIGNAL
};
struct _WebKitAuthenticationRequestPrivate {
RefPtr<AuthenticationChallengeProxy> authenticationChallenge;
bool privateBrowsingEnabled;
bool persistentCredentialStorageEnabled;
bool handledRequest;
CString host;
CString realm;
Optional<WebCore::Credential> proposedCredential;
Optional<WebCore::Credential> acceptedCredential;
Optional<bool> canSaveCredentials;
};
static guint signals[LAST_SIGNAL] = { 0, };
WEBKIT_DEFINE_TYPE(WebKitAuthenticationRequest, webkit_authentication_request, G_TYPE_OBJECT)
static inline WebKitAuthenticationScheme toWebKitAuthenticationScheme(WebCore::ProtectionSpaceAuthenticationScheme coreScheme)
{
switch (coreScheme) {
case WebCore::ProtectionSpaceAuthenticationSchemeDefault:
return WEBKIT_AUTHENTICATION_SCHEME_DEFAULT;
case WebCore::ProtectionSpaceAuthenticationSchemeHTTPBasic:
return WEBKIT_AUTHENTICATION_SCHEME_HTTP_BASIC;
case WebCore::ProtectionSpaceAuthenticationSchemeHTTPDigest:
return WEBKIT_AUTHENTICATION_SCHEME_HTTP_DIGEST;
case WebCore::ProtectionSpaceAuthenticationSchemeHTMLForm:
return WEBKIT_AUTHENTICATION_SCHEME_HTML_FORM;
case WebCore::ProtectionSpaceAuthenticationSchemeNTLM:
return WEBKIT_AUTHENTICATION_SCHEME_NTLM;
case WebCore::ProtectionSpaceAuthenticationSchemeNegotiate:
return WEBKIT_AUTHENTICATION_SCHEME_NEGOTIATE;
case WebCore::ProtectionSpaceAuthenticationSchemeClientCertificateRequested:
return WEBKIT_AUTHENTICATION_SCHEME_CLIENT_CERTIFICATE_REQUESTED;
case WebCore::ProtectionSpaceAuthenticationSchemeServerTrustEvaluationRequested:
return WEBKIT_AUTHENTICATION_SCHEME_SERVER_TRUST_EVALUATION_REQUESTED;
case WebCore::ProtectionSpaceAuthenticationSchemeUnknown:
return WEBKIT_AUTHENTICATION_SCHEME_UNKNOWN;
default:
ASSERT_NOT_REACHED();
return WEBKIT_AUTHENTICATION_SCHEME_DEFAULT;
}
}
static void webkitAuthenticationRequestDispose(GObject* object)
{
WebKitAuthenticationRequest* request = WEBKIT_AUTHENTICATION_REQUEST(object);
webkit_authentication_request_cancel(request);
G_OBJECT_CLASS(webkit_authentication_request_parent_class)->dispose(object);
}
static void webkit_authentication_request_class_init(WebKitAuthenticationRequestClass* requestClass)
{
GObjectClass* objectClass = G_OBJECT_CLASS(requestClass);
objectClass->dispose = webkitAuthenticationRequestDispose;
signals[AUTHENTICATED] =
g_signal_new(
"authenticated",
G_TYPE_FROM_CLASS(objectClass),
G_SIGNAL_RUN_LAST,
0, 0, nullptr,
g_cclosure_marshal_generic,
G_TYPE_NONE, 1,
WEBKIT_TYPE_CREDENTIAL | G_SIGNAL_TYPE_STATIC_SCOPE);
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, bool persistentCredentialStorageEnabled)
{
WebKitAuthenticationRequest* request = WEBKIT_AUTHENTICATION_REQUEST(g_object_new(WEBKIT_TYPE_AUTHENTICATION_REQUEST, NULL));
request->priv->authenticationChallenge = authenticationChallenge;
request->priv->privateBrowsingEnabled = privateBrowsingEnabled;
request->priv->persistentCredentialStorageEnabled = persistentCredentialStorageEnabled;
return request;
}
AuthenticationChallengeProxy* webkitAuthenticationRequestGetAuthenticationChallenge(WebKitAuthenticationRequest* request)
{
return request->priv->authenticationChallenge.get();
}
void webkitAuthenticationRequestDidAuthenticate(WebKitAuthenticationRequest* request)
{
auto* credential = webkitCredentialCreate(request->priv->acceptedCredential.valueOr(WebCore::Credential()));
g_signal_emit(request, signals[AUTHENTICATED], 0, credential);
webkit_credential_free(credential);
}
const WebCore::Credential& webkitAuthenticationRequestGetProposedCredential(WebKitAuthenticationRequest* request)
{
if (request->priv->proposedCredential)
return request->priv->proposedCredential.value();
return request->priv->authenticationChallenge->core().proposedCredential();
}
gboolean webkit_authentication_request_can_save_credentials(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), FALSE);
if (request->priv->privateBrowsingEnabled)
return FALSE;
if (request->priv->canSaveCredentials)
return request->priv->canSaveCredentials.value();
#if USE(LIBSECRET)
return request->priv->persistentCredentialStorageEnabled;
#else
return FALSE;
#endif
}
void webkit_authentication_request_set_can_save_credentials(WebKitAuthenticationRequest* request, gboolean enabled)
{
g_return_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request));
request->priv->canSaveCredentials = enabled;
}
WebKitCredential* webkit_authentication_request_get_proposed_credential(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), nullptr);
const auto& credential = webkitAuthenticationRequestGetProposedCredential(request);
if (credential.isEmpty())
return nullptr;
return webkitCredentialCreate(credential);
}
void webkit_authentication_request_set_proposed_credential(WebKitAuthenticationRequest* request, WebKitCredential* credential)
{
g_return_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request));
if (!credential) {
request->priv->proposedCredential = WTF::nullopt;
return;
}
request->priv->proposedCredential = webkitCredentialGetCredential(credential);
}
const gchar* webkit_authentication_request_get_host(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), 0);
if (request->priv->host.isNull())
request->priv->host = request->priv->authenticationChallenge->core().protectionSpace().host().utf8();
return request->priv->host.data();
}
guint webkit_authentication_request_get_port(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), 0);
return request->priv->authenticationChallenge->core().protectionSpace().port();
}
WebKitSecurityOrigin* webkit_authentication_request_get_security_origin(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), nullptr);
const auto& protectionSpace = request->priv->authenticationChallenge->core().protectionSpace();
String protocol;
switch (protectionSpace.serverType()) {
case ProtectionSpaceServerHTTP:
case ProtectionSpaceProxyHTTP:
protocol = "http"_s;
break;
case ProtectionSpaceServerHTTPS:
case ProtectionSpaceProxyHTTPS:
protocol = "https"_s;
break;
case ProtectionSpaceServerFTP:
case ProtectionSpaceProxyFTP:
protocol = "ftp"_s;
break;
case ProtectionSpaceServerFTPS:
protocol = "ftps"_s;
break;
case ProtectionSpaceProxySOCKS:
protocol = "socks"_s;
break;
}
return webkitSecurityOriginCreate(SecurityOrigin::create(protocol, protectionSpace.host(), protectionSpace.port()));
}
const gchar* webkit_authentication_request_get_realm(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), 0);
if (request->priv->realm.isNull())
request->priv->realm = request->priv->authenticationChallenge->core().protectionSpace().realm().utf8();
return request->priv->realm.data();
}
WebKitAuthenticationScheme webkit_authentication_request_get_scheme(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), WEBKIT_AUTHENTICATION_SCHEME_UNKNOWN);
return toWebKitAuthenticationScheme(request->priv->authenticationChallenge->core().protectionSpace().authenticationScheme());
}
gboolean webkit_authentication_request_is_for_proxy(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), FALSE);
return request->priv->authenticationChallenge->core().protectionSpace().isProxy();
}
gboolean webkit_authentication_request_is_retry(WebKitAuthenticationRequest* request)
{
g_return_val_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request), 0);
return request->priv->authenticationChallenge->core().previousFailureCount() ? TRUE : FALSE;
}
void webkit_authentication_request_authenticate(WebKitAuthenticationRequest* request, WebKitCredential* credential)
{
g_return_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request));
if (credential)
request->priv->acceptedCredential = webkitCredentialGetCredential(credential);
else
request->priv->acceptedCredential = WTF::nullopt;
request->priv->authenticationChallenge->listener().completeChallenge(WebKit::AuthenticationChallengeDisposition::UseCredential, request->priv->acceptedCredential.valueOr(WebCore::Credential()));
request->priv->handledRequest = true;
}
void webkit_authentication_request_cancel(WebKitAuthenticationRequest* request)
{
g_return_if_fail(WEBKIT_IS_AUTHENTICATION_REQUEST(request));
if (request->priv->handledRequest)
return;
request->priv->authenticationChallenge->listener().completeChallenge(WebKit::AuthenticationChallengeDisposition::Cancel);
request->priv->acceptedCredential = WTF::nullopt;
request->priv->handledRequest = true;
g_signal_emit(request, signals[CANCELLED], 0);
}