2
* Copyright (C) 2012 Research In Motion Limited. All rights reserved.
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2 of the License, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
#include "AuthenticationChallengeManager.h"
22
#include "Credential.h"
24
#include "PageClientBlackBerry.h"
25
#include "ProtectionSpace.h"
27
#include <BlackBerryPlatformAssert.h>
28
#include <BlackBerryPlatformLog.h>
29
#include <wtf/Assertions.h>
30
#include <wtf/HashMap.h>
31
#include <wtf/PassOwnPtr.h>
32
#include <wtf/Vector.h>
33
#include <wtf/text/CString.h>
37
typedef HashMap<PageClientBlackBerry*, bool> PageVisibilityMap;
39
struct ChallengeInfo {
40
ChallengeInfo(const KURL&, const ProtectionSpace&, const Credential&, AuthenticationChallengeClient*, PageClientBlackBerry*);
43
ProtectionSpace space;
44
Credential credential;
45
AuthenticationChallengeClient* authClient;
46
PageClientBlackBerry* pageClient;
50
ChallengeInfo::ChallengeInfo(const KURL& aUrl, const ProtectionSpace& aSpace, const Credential& aCredential,
51
AuthenticationChallengeClient* anAuthClient, PageClientBlackBerry* aPageClient)
54
, credential(aCredential)
55
, authClient(anAuthClient)
56
, pageClient(aPageClient)
61
class AuthenticationChallengeManagerPrivate {
63
AuthenticationChallengeManagerPrivate();
65
bool resumeAuthenticationChallenge(PageClientBlackBerry*);
66
void startAuthenticationChallenge(ChallengeInfo*);
67
bool pageExists(PageClientBlackBerry*);
69
ChallengeInfo* m_activeChallenge;
70
PageVisibilityMap m_pageVisibilityMap;
71
Vector<OwnPtr<ChallengeInfo> > m_challenges;
74
AuthenticationChallengeManagerPrivate::AuthenticationChallengeManagerPrivate()
75
: m_activeChallenge(0)
79
bool AuthenticationChallengeManagerPrivate::resumeAuthenticationChallenge(PageClientBlackBerry* client)
81
ASSERT(!m_activeChallenge);
83
for (size_t i = 0; i < m_challenges.size(); ++i) {
84
if (m_challenges[i]->pageClient == client && m_challenges[i]->blocked) {
85
startAuthenticationChallenge(m_challenges[i].get());
93
void AuthenticationChallengeManagerPrivate::startAuthenticationChallenge(ChallengeInfo* info)
95
m_activeChallenge = info;
96
m_activeChallenge->blocked = false;
97
m_activeChallenge->pageClient->authenticationChallenge(m_activeChallenge->url, m_activeChallenge->space, m_activeChallenge->credential);
100
bool AuthenticationChallengeManagerPrivate::pageExists(PageClientBlackBerry* client)
102
return m_pageVisibilityMap.find(client) != m_pageVisibilityMap.end();
105
SINGLETON_INITIALIZER_THREADUNSAFE(AuthenticationChallengeManager)
107
AuthenticationChallengeManager::AuthenticationChallengeManager()
108
: d(adoptPtr(new AuthenticationChallengeManagerPrivate))
112
void AuthenticationChallengeManager::pageCreated(PageClientBlackBerry* client)
114
d->m_pageVisibilityMap.add(client, true);
117
void AuthenticationChallengeManager::pageDeleted(PageClientBlackBerry* client)
119
d->m_pageVisibilityMap.remove(client);
121
if (d->m_activeChallenge && d->m_activeChallenge->pageClient == client)
122
d->m_activeChallenge = 0;
124
Vector<OwnPtr<ChallengeInfo> > existing;
125
d->m_challenges.swap(existing);
127
for (size_t i = 0; i < existing.size(); ++i) {
128
if (existing[i]->pageClient != client)
129
d->m_challenges.append(existing[i].release());
133
void AuthenticationChallengeManager::pageVisibilityChanged(PageClientBlackBerry* client, bool visible)
135
PageVisibilityMap::iterator iter = d->m_pageVisibilityMap.find(client);
137
ASSERT(iter != d->m_pageVisibilityMap.end());
138
if (iter == d->m_pageVisibilityMap.end()) {
139
d->m_pageVisibilityMap.add(client, visible);
143
if (iter->second == visible)
146
iter->second = visible;
150
if (d->m_activeChallenge)
153
d->resumeAuthenticationChallenge(client);
156
void AuthenticationChallengeManager::authenticationChallenge(const KURL& url, const ProtectionSpace& space,
157
const Credential& credential, AuthenticationChallengeClient* authClient, PageClientBlackBerry* pageClient)
159
BLACKBERRY_ASSERT(authClient);
160
BLACKBERRY_ASSERT(pageClient);
162
ChallengeInfo* info = new ChallengeInfo(url, space, credential, authClient, pageClient);
163
d->m_challenges.append(adoptPtr(info));
165
if (d->m_activeChallenge || !pageClient->isVisible()) {
166
info->blocked = true;
170
d->startAuthenticationChallenge(info);
173
void AuthenticationChallengeManager::cancelAuthenticationChallenge(AuthenticationChallengeClient* client)
175
BLACKBERRY_ASSERT(client);
177
if (d->m_activeChallenge && d->m_activeChallenge->authClient == client)
178
d->m_activeChallenge = 0;
180
Vector<OwnPtr<ChallengeInfo> > existing;
181
d->m_challenges.swap(existing);
183
ChallengeInfo* next = 0;
184
PageClientBlackBerry* page = 0;
186
for (size_t i = 0; i < existing.size(); ++i) {
187
if (existing[i]->authClient != client) {
188
if (page && !next && existing[i]->pageClient == page)
189
next = existing[i].get();
190
d->m_challenges.append(existing[i].release());
191
} else if (d->m_activeChallenge == existing[i].get())
192
page = existing[i]->pageClient;
196
d->startAuthenticationChallenge(next);
199
void AuthenticationChallengeManager::notifyChallengeResult(const KURL& url, const ProtectionSpace& space,
200
AuthenticationChallengeResult result, const Credential& credential)
202
d->m_activeChallenge = 0;
204
Vector<OwnPtr<ChallengeInfo> > existing;
205
d->m_challenges.swap(existing);
207
ChallengeInfo* next = 0;
208
PageClientBlackBerry* page = 0;
210
for (size_t i = 0; i < existing.size(); ++i) {
211
if (existing[i]->space != space) {
212
if (page && !next && existing[i]->pageClient == page)
213
next = existing[i].get();
214
d->m_challenges.append(existing[i].release());
216
page = existing[i]->pageClient;
217
existing[i]->authClient->notifyChallengeResult(existing[i]->url, space, result, credential);
219
// After calling notifyChallengeResult(), page could be destroyed or something.
220
if (!d->pageExists(page) || !page->isVisible())
226
d->startAuthenticationChallenge(next);
229
} // namespace WebCore