1/*
2 * Copyright (C) 2012 Intel Corporation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "ewk_auth_request.h"
28
29#include "WKAuthenticationChallenge.h"
30#include "WKAuthenticationDecisionListener.h"
31#include "WKCredential.h"
32#include "WKProtectionSpace.h"
33#include "WKString.h"
34#include "ewk_auth_request_private.h"
35#include <wtf/text/CString.h>
36
37using namespace WebKit;
38
39EwkAuthRequest::EwkAuthRequest(WKAuthenticationChallengeRef authenticationChallenge)
40    : m_authenticationChallenge(authenticationChallenge)
41    , m_wasHandled(false)
42{
43    ASSERT(m_authenticationChallenge);
44}
45
46EwkAuthRequest::~EwkAuthRequest()
47{
48    if (!m_wasHandled)
49        continueWithoutCredential();
50}
51
52const char* EwkAuthRequest::suggestedUsername() const
53{
54    if (!m_suggestedUsername) {
55        WKRetainPtr<WKCredentialRef> credential = WKAuthenticationChallengeGetProposedCredential(m_authenticationChallenge.get());
56        ASSERT(credential);
57
58        WKRetainPtr<WKStringRef> suggestedUsername(AdoptWK, WKCredentialCopyUser(credential.get()));
59        if (!suggestedUsername || WKStringIsEmpty(suggestedUsername.get()))
60            return 0;
61
62        m_suggestedUsername = suggestedUsername.get();
63    }
64
65    return m_suggestedUsername;
66}
67
68const char* EwkAuthRequest::realm() const
69{
70    if (!m_realm) {
71        WKRetainPtr<WKProtectionSpaceRef> protectionSpace = WKAuthenticationChallengeGetProtectionSpace(m_authenticationChallenge.get());
72        ASSERT(protectionSpace);
73
74        WKRetainPtr<WKStringRef> realm(AdoptWK, WKProtectionSpaceCopyRealm(protectionSpace.get()));
75        if (!realm || WKStringIsEmpty(realm.get()))
76            return 0;
77
78        m_realm = realm.get();
79    }
80
81    return m_realm;
82}
83
84const char* EwkAuthRequest::host() const
85{
86    if (!m_host) {
87        WKRetainPtr<WKProtectionSpaceRef> protectionSpace = WKAuthenticationChallengeGetProtectionSpace(m_authenticationChallenge.get());
88        ASSERT(protectionSpace);
89
90        WKRetainPtr<WKStringRef> host(AdoptWK, WKProtectionSpaceCopyHost(protectionSpace.get()));
91        if (!host || WKStringIsEmpty(host.get()))
92            return 0;
93
94        m_host = host.get();
95    }
96
97    return m_host;
98}
99
100bool EwkAuthRequest::continueWithoutCredential()
101{
102    if (m_wasHandled)
103        return false;
104
105    m_wasHandled = true;
106    WKAuthenticationDecisionListenerRef decisionListener = WKAuthenticationChallengeGetDecisionListener(m_authenticationChallenge.get());
107    WKAuthenticationDecisionListenerUseCredential(decisionListener, 0);
108
109    return true;
110}
111
112bool EwkAuthRequest::authenticate(const char* username, const char* password)
113{
114    if (m_wasHandled)
115        return false;
116
117    m_wasHandled = true;
118    WKRetainPtr<WKStringRef> wkUsername(AdoptWK, WKStringCreateWithUTF8CString(username));
119    WKRetainPtr<WKStringRef> wkPassword(AdoptWK, WKStringCreateWithUTF8CString(password));
120    WKRetainPtr<WKCredentialRef> credential(AdoptWK, WKCredentialCreate(wkUsername.get(), wkPassword.get(), kWKCredentialPersistenceForSession));
121    WKAuthenticationDecisionListenerRef decisionListener = WKAuthenticationChallengeGetDecisionListener(m_authenticationChallenge.get());
122    WKAuthenticationDecisionListenerUseCredential(decisionListener, credential.get());
123
124    return true;
125}
126
127bool EwkAuthRequest::isRetrying() const
128{
129    return WKAuthenticationChallengeGetPreviousFailureCount(m_authenticationChallenge.get()) > 0;
130}
131
132const char* ewk_auth_request_suggested_username_get(const Ewk_Auth_Request* request)
133{
134    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkAuthRequest, request, impl, nullptr);
135
136    return impl->suggestedUsername();
137}
138
139Eina_Bool ewk_auth_request_cancel(Ewk_Auth_Request* request)
140{
141    EWK_OBJ_GET_IMPL_OR_RETURN(EwkAuthRequest, request, impl, false);
142
143    return impl->continueWithoutCredential();
144}
145
146Eina_Bool ewk_auth_request_authenticate(Ewk_Auth_Request* request, const char* username, const char* password)
147{
148    EWK_OBJ_GET_IMPL_OR_RETURN(EwkAuthRequest, request, impl, false);
149    EINA_SAFETY_ON_NULL_RETURN_VAL(username, false);
150    EINA_SAFETY_ON_NULL_RETURN_VAL(password, false);
151
152    return impl->authenticate(username, password);
153}
154
155Eina_Bool ewk_auth_request_retrying_get(const Ewk_Auth_Request* request)
156{
157    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkAuthRequest, request, impl, false);
158
159    return impl->isRetrying();
160}
161
162const char* ewk_auth_request_realm_get(const Ewk_Auth_Request* request)
163{
164    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkAuthRequest, request, impl, nullptr);
165
166    return impl->realm();
167}
168
169const char* ewk_auth_request_host_get(const Ewk_Auth_Request* request)
170{
171    EWK_OBJ_GET_IMPL_OR_RETURN(const EwkAuthRequest, request, impl, nullptr);
172
173    return impl->host();
174}
175