Remove unused includes of wtf headers
[WebKit-https.git] / Source / WebCore / platform / network / CredentialStorage.cpp
1 /*
2  * Copyright (C) 2009 Apple Inc. 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. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "CredentialStorage.h"
28
29 #include "NetworkStorageSession.h"
30 #include "URL.h"
31
32 #if PLATFORM(IOS)
33 #include "WebCoreThread.h"
34 #endif
35
36 namespace WebCore {
37
38 CredentialStorage& CredentialStorage::defaultCredentialStorage()
39 {
40     return NetworkStorageSession::defaultStorageSession().credentialStorage();
41 }
42
43 static String originStringFromURL(const URL& url)
44 {
45     if (url.port())
46         return url.protocol() + "://" + url.host() + ':' + String::number(url.port()) + '/';
47
48     return url.protocol() + "://" + url.host() + '/';
49 }
50
51 static String protectionSpaceMapKeyFromURL(const URL& url)
52 {
53     ASSERT(url.isValid());
54
55     // Remove the last path component that is not a directory to determine the subtree for which credentials will apply.
56     // We keep a leading slash, but remove a trailing one.
57     String directoryURL = url.string().substring(0, url.pathEnd());
58     unsigned directoryURLPathStart = url.pathStart();
59     ASSERT(directoryURL[directoryURLPathStart] == '/');
60     if (directoryURL.length() > directoryURLPathStart + 1) {
61         size_t index = directoryURL.reverseFind('/');
62         ASSERT(index != notFound);
63         directoryURL = directoryURL.substring(0, (index != directoryURLPathStart) ? index : directoryURLPathStart + 1);
64     }
65
66     return directoryURL;
67 }
68
69 void CredentialStorage::set(const Credential& credential, const ProtectionSpace& protectionSpace, const URL& url)
70 {
71     ASSERT(protectionSpace.isProxy() || protectionSpace.authenticationScheme() == ProtectionSpaceAuthenticationSchemeClientCertificateRequested || url.protocolIsInHTTPFamily());
72     ASSERT(protectionSpace.isProxy() || protectionSpace.authenticationScheme() == ProtectionSpaceAuthenticationSchemeClientCertificateRequested || url.isValid());
73
74     m_protectionSpaceToCredentialMap.set(protectionSpace, credential);
75
76 #if PLATFORM(IOS)
77     if (protectionSpace.authenticationScheme() != ProtectionSpaceAuthenticationSchemeClientCertificateRequested)
78         saveToPersistentStorage(protectionSpace, credential);
79 #endif
80
81     if (!protectionSpace.isProxy() && protectionSpace.authenticationScheme() != ProtectionSpaceAuthenticationSchemeClientCertificateRequested) {
82         m_originsWithCredentials.add(originStringFromURL(url));
83
84         ProtectionSpaceAuthenticationScheme scheme = protectionSpace.authenticationScheme();
85         if (scheme == ProtectionSpaceAuthenticationSchemeHTTPBasic || scheme == ProtectionSpaceAuthenticationSchemeDefault) {
86             // The map can contain both a path and its subpath - while redundant, this makes lookups faster.
87             m_pathToDefaultProtectionSpaceMap.set(protectionSpaceMapKeyFromURL(url), protectionSpace);
88         }
89     }
90 }
91
92 Credential CredentialStorage::get(const ProtectionSpace& protectionSpace)
93 {
94     return m_protectionSpaceToCredentialMap.get(protectionSpace);
95 }
96
97 void CredentialStorage::remove(const ProtectionSpace& protectionSpace)
98 {
99     m_protectionSpaceToCredentialMap.remove(protectionSpace);
100 }
101
102 HashMap<String, ProtectionSpace>::iterator CredentialStorage::findDefaultProtectionSpaceForURL(const URL& url)
103 {
104     ASSERT(url.protocolIsInHTTPFamily());
105     ASSERT(url.isValid());
106
107     // Don't spend time iterating the path for origins that don't have any credentials.
108     if (!m_originsWithCredentials.contains(originStringFromURL(url)))
109         return m_pathToDefaultProtectionSpaceMap.end();
110
111     String directoryURL = protectionSpaceMapKeyFromURL(url);
112     unsigned directoryURLPathStart = url.pathStart();
113     while (true) {
114         PathToDefaultProtectionSpaceMap::iterator iter = m_pathToDefaultProtectionSpaceMap.find(directoryURL);
115         if (iter != m_pathToDefaultProtectionSpaceMap.end())
116             return iter;
117
118         if (directoryURL.length() == directoryURLPathStart + 1)  // path is "/" already, cannot shorten it any more
119             return m_pathToDefaultProtectionSpaceMap.end();
120
121         size_t index = directoryURL.reverseFind('/', directoryURL.length() - 2);
122         ASSERT(index != notFound);
123         directoryURL = directoryURL.substring(0, (index == directoryURLPathStart) ? index + 1 : index);
124         ASSERT(directoryURL.length() > directoryURLPathStart);
125     }
126 }
127
128 bool CredentialStorage::set(const Credential& credential, const URL& url)
129 {
130     ASSERT(url.protocolIsInHTTPFamily());
131     ASSERT(url.isValid());
132     PathToDefaultProtectionSpaceMap::iterator iter = findDefaultProtectionSpaceForURL(url);
133     if (iter == m_pathToDefaultProtectionSpaceMap.end())
134         return false;
135     ASSERT(m_originsWithCredentials.contains(originStringFromURL(url)));
136     m_protectionSpaceToCredentialMap.set(iter->value, credential);
137     return true;
138 }
139
140 Credential CredentialStorage::get(const URL& url)
141 {
142     PathToDefaultProtectionSpaceMap::iterator iter = findDefaultProtectionSpaceForURL(url);
143     if (iter == m_pathToDefaultProtectionSpaceMap.end())
144         return Credential();
145     return m_protectionSpaceToCredentialMap.get(iter->value);
146 }
147
148 void CredentialStorage::clearCredentials()
149 {
150     m_protectionSpaceToCredentialMap.clear();
151     m_originsWithCredentials.clear();
152     m_pathToDefaultProtectionSpaceMap.clear();
153 }
154
155 } // namespace WebCore