summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/network
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/network')
-rw-r--r--WebCore/platform/network/AuthenticationClient.h53
-rw-r--r--WebCore/platform/network/Credential.cpp80
-rw-r--r--WebCore/platform/network/Credential.h31
-rw-r--r--WebCore/platform/network/CredentialStorage.cpp18
-rw-r--r--WebCore/platform/network/CredentialStorage.h4
-rw-r--r--WebCore/platform/network/FormDataBuilder.cpp21
-rw-r--r--WebCore/platform/network/HTTPHeaderMap.cpp36
-rw-r--r--WebCore/platform/network/HTTPHeaderMap.h16
-rw-r--r--WebCore/platform/network/NetworkStateNotifier.h4
-rw-r--r--WebCore/platform/network/ProtectionSpace.cpp3
-rw-r--r--WebCore/platform/network/ProtectionSpaceHash.h10
-rw-r--r--WebCore/platform/network/ResourceHandle.cpp95
-rw-r--r--WebCore/platform/network/ResourceHandle.h24
-rw-r--r--WebCore/platform/network/ResourceHandleClient.h2
-rw-r--r--WebCore/platform/network/ResourceHandleInternal.h12
-rw-r--r--WebCore/platform/network/ResourceRequestBase.cpp12
-rw-r--r--WebCore/platform/network/ResourceRequestBase.h26
-rw-r--r--WebCore/platform/network/ResourceResponseBase.cpp7
-rw-r--r--WebCore/platform/network/ResourceResponseBase.h1
-rw-r--r--WebCore/platform/network/SocketStreamHandleBase.cpp5
-rw-r--r--WebCore/platform/network/SocketStreamHandleClient.h5
-rw-r--r--WebCore/platform/network/cf/AuthenticationCF.cpp8
-rw-r--r--WebCore/platform/network/cf/AuthenticationChallenge.h12
-rw-r--r--WebCore/platform/network/cf/CredentialStorageCFNet.cpp44
-rw-r--r--WebCore/platform/network/cf/DNSCFNet.cpp4
-rw-r--r--WebCore/platform/network/cf/LoaderRunLoopCF.cpp66
-rw-r--r--WebCore/platform/network/cf/LoaderRunLoopCF.h39
-rw-r--r--WebCore/platform/network/cf/ResourceHandleCFNet.cpp37
-rw-r--r--WebCore/platform/network/cf/ResourceRequest.h6
-rw-r--r--WebCore/platform/network/cf/ResourceRequestCFNet.h2
-rw-r--r--WebCore/platform/network/cf/SocketStreamHandle.h64
-rw-r--r--WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp587
-rw-r--r--WebCore/platform/network/chromium/AuthenticationChallenge.h8
-rw-r--r--WebCore/platform/network/chromium/CookieJarChromium.cpp10
-rw-r--r--WebCore/platform/network/chromium/ResourceRequest.cpp3
-rw-r--r--WebCore/platform/network/chromium/ResourceRequest.h20
-rw-r--r--WebCore/platform/network/curl/AuthenticationChallenge.h8
-rw-r--r--WebCore/platform/network/curl/ResourceHandleManager.cpp5
-rw-r--r--WebCore/platform/network/curl/ResourceRequest.h4
-rw-r--r--WebCore/platform/network/mac/AuthenticationChallenge.h12
-rw-r--r--WebCore/platform/network/mac/AuthenticationMac.mm97
-rw-r--r--WebCore/platform/network/mac/CredentialStorageMac.mm40
-rw-r--r--WebCore/platform/network/mac/NetworkStateNotifierMac.cpp8
-rw-r--r--WebCore/platform/network/mac/ResourceHandleMac.mm34
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.cpp35
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.h4
-rw-r--r--WebCore/platform/network/qt/ResourceHandleQt.cpp39
-rw-r--r--WebCore/platform/network/qt/ResourceRequest.h9
-rw-r--r--WebCore/platform/network/qt/ResourceRequestQt.cpp14
-rw-r--r--WebCore/platform/network/soup/DNSSoup.cpp11
-rw-r--r--WebCore/platform/network/soup/ResourceHandleSoup.cpp16
-rw-r--r--WebCore/platform/network/soup/ResourceRequest.h6
-rw-r--r--WebCore/platform/network/soup/ResourceResponse.h7
-rw-r--r--WebCore/platform/network/soup/ResourceResponseSoup.cpp18
54 files changed, 1382 insertions, 360 deletions
diff --git a/WebCore/platform/network/AuthenticationClient.h b/WebCore/platform/network/AuthenticationClient.h
new file mode 100644
index 0000000..1e17910
--- /dev/null
+++ b/WebCore/platform/network/AuthenticationClient.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef AuthenticationClient_h
+#define AuthenticationClient_h
+
+namespace WebCore {
+
+class AuthenticationChallenge;
+class Credential;
+
+class AuthenticationClient {
+public:
+ virtual void receivedCredential(const AuthenticationChallenge&, const Credential&) = 0;
+ virtual void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) = 0;
+ virtual void receivedCancellation(const AuthenticationChallenge&) = 0;
+
+ void ref() { refAuthenticationClient(); }
+ void deref() { derefAuthenticationClient(); }
+
+protected:
+ virtual ~AuthenticationClient() { }
+
+private:
+ virtual void refAuthenticationClient() = 0;
+ virtual void derefAuthenticationClient() = 0;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/network/Credential.cpp b/WebCore/platform/network/Credential.cpp
index f905743..87cd7ff 100644
--- a/WebCore/platform/network/Credential.cpp
+++ b/WebCore/platform/network/Credential.cpp
@@ -33,6 +33,9 @@ Credential::Credential()
: m_user("")
, m_password("")
, m_persistence(CredentialPersistenceNone)
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ , m_type(CredentialTypePassword)
+#endif
{
}
@@ -42,11 +45,31 @@ Credential::Credential(const String& user, const String& password, CredentialPer
: m_user(user.length() ? user : "")
, m_password(password.length() ? password : "")
, m_persistence(persistence)
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ , m_type(CredentialTypePassword)
+#endif
+{
+}
+
+Credential::Credential(const Credential& original, CredentialPersistence persistence)
+ : m_user(original.user())
+ , m_password(original.password())
+ , m_persistence(persistence)
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ , m_identity(original.identity())
+ , m_certificates(original.certificates())
+ , m_type(original.type())
+#endif
{
}
bool Credential::isEmpty() const
{
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ if (m_type == CredentialTypeClientCertificate && (m_identity || m_certificates))
+ return false;
+#endif
+
return m_user.isEmpty() && m_password.isEmpty();
}
@@ -69,15 +92,68 @@ CredentialPersistence Credential::persistence() const
{
return m_persistence;
}
+
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+Credential::Credential(SecIdentityRef identity, CFArrayRef certificates, CredentialPersistence persistence)
+ : m_user("")
+ , m_password("")
+ , m_persistence(persistence)
+ , m_identity(identity)
+ , m_certificates(certificates)
+ , m_type(CredentialTypeClientCertificate)
+{
+}
+
+SecIdentityRef Credential::identity() const
+{
+ return m_identity.get();
+}
+
+CFArrayRef Credential::certificates() const
+{
+ return m_certificates.get();
+}
+
+const CredentialType Credential::type() const
+{
+ return m_type;
+}
+#endif
bool operator==(const Credential& a, const Credential& b)
{
+ // Check persistence first since all credential types
+ // have the persistence property.
+ if (a.persistence() != b.persistence())
+ return false;
+
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ CredentialType aType = a.type();
+ if (aType != b.type())
+ return false;
+
+ // Comparing identity and certificate chain pointers is valid only
+ // for client certificate type credentials.
+ //
+ // FIXME: Is pointer comparison of the identity and certificates properties sufficient?
+ if (aType == CredentialTypeClientCertificate) {
+ if (a.identity() != b.identity())
+ return false;
+ if (a.certificates() != b.certificates())
+ return false;
+
+ // We only need to check identity and certificates to compare
+ // client certificate based credentials.
+ return true;
+ }
+
+ ASSERT(a.type() == CredentialTypePassword && b.type() == CredentialTypePassword);
+#endif
+
if (a.user() != b.user())
return false;
if (a.password() != b.password())
return false;
- if (a.persistence() != b.persistence())
- return false;
return true;
}
diff --git a/WebCore/platform/network/Credential.h b/WebCore/platform/network/Credential.h
index 0471fbc..199817c 100644
--- a/WebCore/platform/network/Credential.h
+++ b/WebCore/platform/network/Credential.h
@@ -27,6 +27,13 @@
#include "PlatformString.h"
+#define CERTIFICATE_CREDENTIALS_SUPPORTED ((PLATFORM(MAC) || PLATFORM(IPHONE)) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
+
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+#include <Security/SecBase.h>
+#include <wtf/RetainPtr.h>
+#endif
+
namespace WebCore {
enum CredentialPersistence {
@@ -34,12 +41,23 @@ enum CredentialPersistence {
CredentialPersistenceForSession,
CredentialPersistencePermanent
};
-
+
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+enum CredentialType {
+ CredentialTypePassword,
+ CredentialTypeClientCertificate
+};
+#endif
+
class Credential {
public:
Credential();
Credential(const String& user, const String& password, CredentialPersistence);
+ Credential(const Credential& original, CredentialPersistence);
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ Credential(SecIdentityRef identity, CFArrayRef certificates, CredentialPersistence);
+#endif
bool isEmpty() const;
@@ -48,10 +66,21 @@ public:
bool hasPassword() const;
CredentialPersistence persistence() const;
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ SecIdentityRef identity() const;
+ CFArrayRef certificates() const;
+ const CredentialType type() const;
+#endif
+
private:
String m_user;
String m_password;
CredentialPersistence m_persistence;
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ RetainPtr<SecIdentityRef> m_identity;
+ RetainPtr<CFArrayRef> m_certificates;
+ CredentialType m_type;
+#endif
};
bool operator==(const Credential& a, const Credential& b);
diff --git a/WebCore/platform/network/CredentialStorage.cpp b/WebCore/platform/network/CredentialStorage.cpp
index ec78372..a401751 100644
--- a/WebCore/platform/network/CredentialStorage.cpp
+++ b/WebCore/platform/network/CredentialStorage.cpp
@@ -85,16 +85,18 @@ static String protectionSpaceMapKeyFromURL(const KURL& url)
void CredentialStorage::set(const Credential& credential, const ProtectionSpace& protectionSpace, const KURL& url)
{
- ASSERT(url.protocolInHTTPFamily());
- ASSERT(url.isValid());
+ ASSERT(protectionSpace.isProxy() || url.protocolInHTTPFamily());
+ ASSERT(protectionSpace.isProxy() || url.isValid());
protectionSpaceToCredentialMap().set(protectionSpace, credential);
- originsWithCredentials().add(originStringFromURL(url));
-
- ProtectionSpaceAuthenticationScheme scheme = protectionSpace.authenticationScheme();
- if (scheme == ProtectionSpaceAuthenticationSchemeHTTPBasic || scheme == ProtectionSpaceAuthenticationSchemeDefault) {
- // The map can contain both a path and its subpath - while redundant, this makes lookups faster.
- pathToDefaultProtectionSpaceMap().set(protectionSpaceMapKeyFromURL(url), protectionSpace);
+ if (!protectionSpace.isProxy()) {
+ originsWithCredentials().add(originStringFromURL(url));
+
+ ProtectionSpaceAuthenticationScheme scheme = protectionSpace.authenticationScheme();
+ if (scheme == ProtectionSpaceAuthenticationSchemeHTTPBasic || scheme == ProtectionSpaceAuthenticationSchemeDefault) {
+ // The map can contain both a path and its subpath - while redundant, this makes lookups faster.
+ pathToDefaultProtectionSpaceMap().set(protectionSpaceMapKeyFromURL(url), protectionSpace);
+ }
}
}
diff --git a/WebCore/platform/network/CredentialStorage.h b/WebCore/platform/network/CredentialStorage.h
index 5086f69..21fcbad 100644
--- a/WebCore/platform/network/CredentialStorage.h
+++ b/WebCore/platform/network/CredentialStorage.h
@@ -34,9 +34,13 @@ class ProtectionSpace;
class CredentialStorage {
public:
+ // WebCore session credential storage.
static void set(const Credential&, const ProtectionSpace&, const KURL&);
static Credential get(const ProtectionSpace&);
+ // OS persistent storage.
+ static Credential getFromPersistentStorage(const ProtectionSpace&);
+
// These methods work for authentication schemes that support sending credentials without waiting for a request. E.g., for HTTP Basic authentication scheme
// a client should assume that all paths at or deeper than the depth of a known protected resource share are within the same protection space.
static bool set(const Credential&, const KURL&); // Returns true if the URL corresponds to a known protection space, so credentials could be updated.
diff --git a/WebCore/platform/network/FormDataBuilder.cpp b/WebCore/platform/network/FormDataBuilder.cpp
index 04c7527..52f62f3 100644
--- a/WebCore/platform/network/FormDataBuilder.cpp
+++ b/WebCore/platform/network/FormDataBuilder.cpp
@@ -127,9 +127,6 @@ static void appendQuotedString(Vector<char>& buffer, const CString& string)
case '"':
append(buffer, "%22");
break;
- case '%':
- append(buffer, "%25");
- break;
default:
append(buffer, c);
}
@@ -143,7 +140,10 @@ Vector<char> FormDataBuilder::generateUniqueBoundaryString()
// The RFC 2046 spec says the alphanumeric characters plus the
// following characters are legal for boundaries: '()+_,-./:=?
// However the following characters, though legal, cause some sites
- // to fail: (),./:= (http://bugs.webkit.org/show_bug.cgi?id=13352)
+ // to fail: (),./:=+
+ // Note that our algorithm makes it twice as much likely for 'A' or 'B'
+ // to appear in the boundary string, because 0x41 and 0x42 are present in
+ // the below array twice.
static const char alphaNumericEncodingMap[64] = {
0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
@@ -152,18 +152,7 @@ Vector<char> FormDataBuilder::generateUniqueBoundaryString()
0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E,
0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33,
- 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x41
- // FIXME <rdar://problem/5252577> gmail does not accept legal characters in the form boundary
- // As stated above, some legal characters cause, sites to fail. Specifically
- // the / character which was the last character in the above array. I have
- // replaced the last character with another character already in the array
- // (notice the first and last values are both 0x41, A). Instead of picking
- // another unique legal character for boundary strings that, because it has
- // never been tested, may or may not break other sites, I simply
- // replaced / with A. This means A is twice as likely to occur in our boundary
- // strings than any other character but I think this is fine for the time being.
- // The FIXME here is about restoring the / character once the aforementioned
- // radar has been resolved.
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42
};
// Start with an informative prefix.
diff --git a/WebCore/platform/network/HTTPHeaderMap.cpp b/WebCore/platform/network/HTTPHeaderMap.cpp
index 07c66e8..413fb7b 100644
--- a/WebCore/platform/network/HTTPHeaderMap.cpp
+++ b/WebCore/platform/network/HTTPHeaderMap.cpp
@@ -59,5 +59,41 @@ void HTTPHeaderMap::adopt(auto_ptr<CrossThreadHTTPHeaderMapData> data)
set(header.first, header.second);
}
}
+
+// Adapter that allows the HashMap to take C strings as keys.
+struct CaseFoldingCStringTranslator {
+ static unsigned hash(const char* cString)
+ {
+ return CaseFoldingHash::hash(cString, strlen(cString));
+ }
+
+ static bool equal(const AtomicString& key, const char* cString)
+ {
+ return equalIgnoringCase(key, cString);
+ }
+
+ static void translate(AtomicString& location, const char* cString, unsigned /*hash*/)
+ {
+ location = AtomicString(cString);
+ }
+};
+
+String HTTPHeaderMap::get(const char* name) const
+{
+ const_iterator i = find<const char*, CaseFoldingCStringTranslator>(name);
+ if (i == end())
+ return String();
+ return i->second;
+}
+
+bool HTTPHeaderMap::contains(const char* name) const
+{
+ return find<const char*, CaseFoldingCStringTranslator>(name) != end();
+}
+
+pair<HTTPHeaderMap::iterator, bool> HTTPHeaderMap::add(const char* name, const String& value)
+{
+ return HashMap<AtomicString, String, CaseFoldingHash>::add<const char*, CaseFoldingCStringTranslator>(name, value);
+}
} // namespace WebCore
diff --git a/WebCore/platform/network/HTTPHeaderMap.h b/WebCore/platform/network/HTTPHeaderMap.h
index 6da1b90..dfde974 100644
--- a/WebCore/platform/network/HTTPHeaderMap.h
+++ b/WebCore/platform/network/HTTPHeaderMap.h
@@ -45,6 +45,22 @@ namespace WebCore {
std::auto_ptr<CrossThreadHTTPHeaderMapData> copyData() const;
void adopt(std::auto_ptr<CrossThreadHTTPHeaderMapData>);
+
+ String get(const AtomicString& name) const
+ {
+ return HashMap<AtomicString, String, CaseFoldingHash>::get(name);
+ }
+
+ pair<iterator, bool> add(const AtomicString& name, const String& value)
+ {
+ return HashMap<AtomicString, String, CaseFoldingHash>::add(name, value);
+ }
+
+ // Alternate accessors that are faster than converting the char* to AtomicString first.
+ bool contains(const char*) const;
+ String get(const char*) const;
+ pair<iterator, bool> add(const char* name, const String& value);
+
};
} // namespace WebCore
diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h
index f918be6..a630ccd 100644
--- a/WebCore/platform/network/NetworkStateNotifier.h
+++ b/WebCore/platform/network/NetworkStateNotifier.h
@@ -26,6 +26,8 @@
#ifndef NetworkStateNotifier_h
#define NetworkStateNotifier_h
+#include <wtf/Noncopyable.h>
+
#if PLATFORM(MAC)
#include <wtf/RetainPtr.h>
@@ -46,7 +48,7 @@ typedef const struct __SCDynamicStore * SCDynamicStoreRef;
namespace WebCore {
-class NetworkStateNotifier {
+class NetworkStateNotifier : public Noncopyable {
public:
NetworkStateNotifier();
void setNetworkStateChangedFunction(void (*)());
diff --git a/WebCore/platform/network/ProtectionSpace.cpp b/WebCore/platform/network/ProtectionSpace.cpp
index d04bcbe..26c258f 100644
--- a/WebCore/platform/network/ProtectionSpace.cpp
+++ b/WebCore/platform/network/ProtectionSpace.cpp
@@ -111,7 +111,8 @@ bool operator==(const ProtectionSpace& a, const ProtectionSpace& b)
return false;
if (a.serverType() != b.serverType())
return false;
- if (a.realm() != b.realm())
+ // Ignore realm for proxies
+ if (!a.isProxy() && a.realm() != b.realm())
return false;
if (a.authenticationScheme() != b.authenticationScheme())
return false;
diff --git a/WebCore/platform/network/ProtectionSpaceHash.h b/WebCore/platform/network/ProtectionSpaceHash.h
index 6f68b5b..f8c84e8 100644
--- a/WebCore/platform/network/ProtectionSpaceHash.h
+++ b/WebCore/platform/network/ProtectionSpaceHash.h
@@ -37,11 +37,15 @@ struct ProtectionSpaceHash {
protectionSpace.host().impl() ? protectionSpace.host().impl()->hash() : 0,
protectionSpace.port(),
protectionSpace.serverType(),
- protectionSpace.realm().impl() ? protectionSpace.realm().impl()->hash() : 0,
- protectionSpace.authenticationScheme()
+ protectionSpace.authenticationScheme(),
+ protectionSpace.realm().impl() ? protectionSpace.realm().impl()->hash() : 0
};
- return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), sizeof(hashCodes) / sizeof(UChar));
+ unsigned codeCount = sizeof(hashCodes) / sizeof(UChar);
+ // Ignore realm for proxies.
+ if (protectionSpace.isProxy())
+ codeCount -= sizeof(hashCodes[0]) / sizeof(UChar);
+ return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), codeCount);
}
static bool equal(const ProtectionSpace& a, const ProtectionSpace& b) { return a == b; }
diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp
index 5a40b21..7c20561 100644
--- a/WebCore/platform/network/ResourceHandle.cpp
+++ b/WebCore/platform/network/ResourceHandle.cpp
@@ -36,8 +36,6 @@ namespace WebCore {
static bool shouldForceContentSniffing;
-static bool portAllowed(const ResourceRequest&);
-
ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading,
bool shouldContentSniff, bool mightDownloadFromHandle)
: d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle))
@@ -57,7 +55,7 @@ PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request
return newHandle.release();
}
- if (!portAllowed(request)) {
+ if (!portAllowed(request.url())) {
newHandle->scheduleFailure(BlockedFailure);
return newHandle.release();
}
@@ -110,100 +108,9 @@ void ResourceHandle::clearAuthentication()
{
#if PLATFORM(MAC)
d->m_currentMacChallenge = nil;
-#elif USE(CFNETWORK)
- d->m_currentCFChallenge = 0;
#endif
d->m_currentWebChallenge.nullify();
}
-
-static bool portAllowed(const ResourceRequest& request)
-{
- unsigned short port = request.url().port();
-
- // Since most URLs don't have a port, return early for the "no port" case.
- if (!port)
- return true;
-
- // This blocked port list matches the port blocking that Mozilla implements.
- // See http://www.mozilla.org/projects/netlib/PortBanning.html for more information.
- static const unsigned short blockedPortList[] = {
- 1, // tcpmux
- 7, // echo
- 9, // discard
- 11, // systat
- 13, // daytime
- 15, // netstat
- 17, // qotd
- 19, // chargen
- 20, // FTP-data
- 21, // FTP-control
- 22, // SSH
- 23, // telnet
- 25, // SMTP
- 37, // time
- 42, // name
- 43, // nicname
- 53, // domain
- 77, // priv-rjs
- 79, // finger
- 87, // ttylink
- 95, // supdup
- 101, // hostriame
- 102, // iso-tsap
- 103, // gppitnp
- 104, // acr-nema
- 109, // POP2
- 110, // POP3
- 111, // sunrpc
- 113, // auth
- 115, // SFTP
- 117, // uucp-path
- 119, // nntp
- 123, // NTP
- 135, // loc-srv / epmap
- 139, // netbios
- 143, // IMAP2
- 179, // BGP
- 389, // LDAP
- 465, // SMTP+SSL
- 512, // print / exec
- 513, // login
- 514, // shell
- 515, // printer
- 526, // tempo
- 530, // courier
- 531, // Chat
- 532, // netnews
- 540, // UUCP
- 556, // remotefs
- 563, // NNTP+SSL
- 587, // ESMTP
- 601, // syslog-conn
- 636, // LDAP+SSL
- 993, // IMAP+SSL
- 995, // POP3+SSL
- 2049, // NFS
- 3659, // apple-sasl / PasswordServer [Apple addition]
- 4045, // lockd
- 6000, // X11
- };
- const unsigned short* const blockedPortListEnd = blockedPortList
- + sizeof(blockedPortList) / sizeof(blockedPortList[0]);
-
- // If the port is not in the blocked port list, allow it.
- if (!std::binary_search(blockedPortList, blockedPortListEnd, port))
- return true;
-
- // Allow ports 21 and 22 for FTP URLs, as Mozilla does.
- if ((port == 21 || port == 22) && request.url().protocolIs("ftp"))
- return true;
-
- // Allow any port number in a file URL, since the port number is ignored.
- if (request.url().protocolIs("file"))
- return true;
-
- return false;
-}
bool ResourceHandle::shouldContentSniff() const
{
diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h
index e82e13b..e7f6092 100644
--- a/WebCore/platform/network/ResourceHandle.h
+++ b/WebCore/platform/network/ResourceHandle.h
@@ -27,6 +27,7 @@
#define ResourceHandle_h
#include "AuthenticationChallenge.h"
+#include "AuthenticationClient.h"
#include "HTTPHeaderMap.h"
#include "ThreadableLoader.h"
#include <wtf/OwnPtr.h>
@@ -84,14 +85,18 @@ class KURL;
class ResourceError;
class ResourceHandleClient;
class ResourceHandleInternal;
-struct ResourceRequest;
+class ResourceRequest;
class ResourceResponse;
class SchedulePair;
class SharedBuffer;
template <typename T> class Timer;
-class ResourceHandle : public RefCounted<ResourceHandle> {
+class ResourceHandle : public RefCounted<ResourceHandle>
+#if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL)
+ , public AuthenticationClient
+#endif
+ {
private:
ResourceHandle(const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle);
@@ -110,7 +115,7 @@ public:
static bool didSendBodyDataDelegateExists();
#endif
- ~ResourceHandle();
+ virtual ~ResourceHandle();
#if PLATFORM(MAC) || USE(CFNETWORK)
void willSendRequest(ResourceRequest&, const ResourceResponse& redirectResponse);
@@ -118,9 +123,9 @@ public:
#endif
#if PLATFORM(MAC) || USE(CFNETWORK) || USE(CURL)
void didReceiveAuthenticationChallenge(const AuthenticationChallenge&);
- void receivedCredential(const AuthenticationChallenge&, const Credential&);
- void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&);
- void receivedCancellation(const AuthenticationChallenge&);
+ virtual void receivedCredential(const AuthenticationChallenge&, const Credential&);
+ virtual void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&);
+ virtual void receivedCancellation(const AuthenticationChallenge&);
#endif
#if PLATFORM(MAC)
@@ -133,7 +138,6 @@ public:
void schedule(SchedulePair*);
void unschedule(SchedulePair*);
#elif USE(CFNETWORK)
- static CFRunLoopRef loaderRunLoop();
CFURLConnectionRef connection() const;
CFURLConnectionRef releaseConnectionForDownload();
static void setHostAllowsAnyHTTPSCertificate(const String&);
@@ -190,11 +194,17 @@ public:
void fireFailure(Timer<ResourceHandle>*);
+ using RefCounted<ResourceHandle>::ref;
+ using RefCounted<ResourceHandle>::deref;
+
private:
void scheduleFailure(FailureType);
bool start(Frame*);
+ virtual void refAuthenticationClient() { ref(); }
+ virtual void derefAuthenticationClient() { deref(); }
+
friend class ResourceHandleInternal;
OwnPtr<ResourceHandleInternal> d;
};
diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h
index c99be54..b5efaed 100644
--- a/WebCore/platform/network/ResourceHandleClient.h
+++ b/WebCore/platform/network/ResourceHandleClient.h
@@ -50,7 +50,7 @@ namespace WebCore {
class KURL;
class ResourceHandle;
class ResourceError;
- struct ResourceRequest;
+ class ResourceRequest;
class ResourceResponse;
enum CacheStoragePolicy {
diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h
index fa939db..8313560 100644
--- a/WebCore/platform/network/ResourceHandleInternal.h
+++ b/WebCore/platform/network/ResourceHandleInternal.h
@@ -132,8 +132,6 @@ namespace WebCore {
, m_startWhenScheduled(false)
, m_needsSiteSpecificQuirks(false)
, m_currentMacChallenge(nil)
-#elif USE(CFNETWORK)
- , m_currentCFChallenge(0)
#endif
#if PLATFORM(ANDROID)
, m_loader(0)
@@ -211,24 +209,24 @@ namespace WebCore {
Frame* m_frame;
#endif
#if PLATFORM(QT)
-#if QT_VERSION < 0x040400
- QWebNetworkJob* m_job;
-#else
QNetworkReplyHandler* m_job;
-#endif
QWebFrame* m_frame;
#endif
- // FIXME: The platform challenge is almost identical to the one stored in m_currentWebChallenge, but it has a different sender. We only need to store a sender reference here.
#if PLATFORM(MAC)
+ // We need to keep a reference to the original challenge to be able to cancel it.
+ // It is almost identical to m_currentWebChallenge.nsURLAuthenticationChallenge(), but has a different sender.
NSURLAuthenticationChallenge *m_currentMacChallenge;
#endif
+<<<<<<< HEAD:WebCore/platform/network/ResourceHandleInternal.h
#if USE(CFNETWORK)
CFURLAuthChallengeRef m_currentCFChallenge;
#endif
#if PLATFORM(ANDROID)
RefPtr<ResourceLoaderAndroid> m_loader;
#endif
+=======
+>>>>>>> webkit.org at r51976:WebCore/platform/network/ResourceHandleInternal.h
AuthenticationChallenge m_currentWebChallenge;
ResourceHandle::FailureType m_failureType;
diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp
index 936f26b..41afb92 100644
--- a/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/WebCore/platform/network/ResourceRequestBase.cpp
@@ -208,6 +208,13 @@ String ResourceRequestBase::httpHeaderField(const AtomicString& name) const
return m_httpHeaderFields.get(name);
}
+String ResourceRequestBase::httpHeaderField(const char* name) const
+{
+ updateResourceRequest();
+
+ return m_httpHeaderFields.get(name);
+}
+
void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const String& value)
{
updateResourceRequest();
@@ -218,6 +225,11 @@ void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const Str
m_platformRequestUpdated = false;
}
+void ResourceRequestBase::setHTTPHeaderField(const char* name, const String& value)
+{
+ setHTTPHeaderField(AtomicString(name), value);
+}
+
void ResourceRequestBase::clearHTTPReferrer()
{
updateResourceRequest();
diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h
index 84a7bd0..931a9de 100644
--- a/WebCore/platform/network/ResourceRequestBase.h
+++ b/WebCore/platform/network/ResourceRequestBase.h
@@ -46,12 +46,25 @@ namespace WebCore {
const int unspecifiedTimeoutInterval = INT_MAX;
- struct ResourceRequest;
+ class ResourceRequest;
struct CrossThreadResourceRequestData;
// Do not use this type directly. Use ResourceRequest instead.
class ResourceRequestBase {
public:
+ // The type of this ResourceRequest, based on how the resource will be used.
+ enum TargetType {
+ TargetIsMainFrame,
+ TargetIsSubframe,
+ TargetIsSubresource, // Resource is a generic subresource. (Generally a specific type should be specified)
+ TargetIsStyleSheet,
+ TargetIsScript,
+ TargetIsFontResource,
+ TargetIsImage,
+ TargetIsObject,
+ TargetIsMedia
+ };
+
static std::auto_ptr<ResourceRequest> adopt(std::auto_ptr<CrossThreadResourceRequestData>);
// Gets a copy of the data suitable for passing to another thread.
@@ -79,7 +92,9 @@ namespace WebCore {
const HTTPHeaderMap& httpHeaderFields() const;
String httpHeaderField(const AtomicString& name) const;
+ String httpHeaderField(const char* name) const;
void setHTTPHeaderField(const AtomicString& name, const String& value);
+ void setHTTPHeaderField(const char* name, const String& value);
void addHTTPHeaderField(const AtomicString& name, const String& value);
void addHTTPHeaderFields(const HTTPHeaderMap& headerFields);
@@ -115,12 +130,17 @@ namespace WebCore {
bool reportUploadProgress() const { return m_reportUploadProgress; }
void setReportUploadProgress(bool reportUploadProgress) { m_reportUploadProgress = reportUploadProgress; }
+ // What this request is for.
+ TargetType targetType() const { return m_targetType; }
+ void setTargetType(TargetType type) { m_targetType = type; }
+
protected:
// Used when ResourceRequest is initialized from a platform representation of the request
ResourceRequestBase()
: m_resourceRequestUpdated(false)
, m_platformRequestUpdated(true)
, m_reportUploadProgress(false)
+ , m_targetType(TargetIsSubresource)
{
}
@@ -133,6 +153,7 @@ namespace WebCore {
, m_resourceRequestUpdated(true)
, m_platformRequestUpdated(false)
, m_reportUploadProgress(false)
+ , m_targetType(TargetIsSubresource)
{
}
@@ -152,6 +173,7 @@ namespace WebCore {
mutable bool m_resourceRequestUpdated;
mutable bool m_platformRequestUpdated;
bool m_reportUploadProgress;
+ TargetType m_targetType;
private:
const ResourceRequest& asResourceRequest() const;
@@ -162,7 +184,7 @@ namespace WebCore {
bool operator==(const ResourceRequestBase&, const ResourceRequestBase&);
inline bool operator!=(ResourceRequestBase& a, const ResourceRequestBase& b) { return !(a == b); }
- struct CrossThreadResourceRequestData {
+ struct CrossThreadResourceRequestData : Noncopyable {
KURL m_url;
ResourceRequestCachePolicy m_cachePolicy;
diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp
index fd44225..f9cd271 100644
--- a/WebCore/platform/network/ResourceResponseBase.cpp
+++ b/WebCore/platform/network/ResourceResponseBase.cpp
@@ -239,6 +239,13 @@ String ResourceResponseBase::httpHeaderField(const AtomicString& name) const
return m_httpHeaderFields.get(name);
}
+String ResourceResponseBase::httpHeaderField(const char* name) const
+{
+ lazyInit();
+
+ return m_httpHeaderFields.get(name);
+}
+
void ResourceResponseBase::setHTTPHeaderField(const AtomicString& name, const String& value)
{
lazyInit();
diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h
index 7594c09..e06c6f8 100644
--- a/WebCore/platform/network/ResourceResponseBase.h
+++ b/WebCore/platform/network/ResourceResponseBase.h
@@ -71,6 +71,7 @@ public:
void setHTTPStatusText(const String&);
String httpHeaderField(const AtomicString& name) const;
+ String httpHeaderField(const char* name) const;
void setHTTPHeaderField(const AtomicString& name, const String& value);
const HTTPHeaderMap& httpHeaderFields() const;
diff --git a/WebCore/platform/network/SocketStreamHandleBase.cpp b/WebCore/platform/network/SocketStreamHandleBase.cpp
index 875c248..8472713 100644
--- a/WebCore/platform/network/SocketStreamHandleBase.cpp
+++ b/WebCore/platform/network/SocketStreamHandleBase.cpp
@@ -31,6 +31,7 @@
#include "config.h"
#include "SocketStreamHandleBase.h"
+#include "SocketStreamHandle.h"
#include "SocketStreamHandleClient.h"
namespace WebCore {
@@ -64,7 +65,7 @@ bool SocketStreamHandleBase::send(const char* data, int length)
int bytesWritten = 0;
if (m_state == Open)
bytesWritten = platformSend(data, length);
- if (bytesWritten <= 0)
+ if (bytesWritten < 0)
return false;
if (m_buffer.size() + length - bytesWritten > bufferSize) {
// FIXME: report error to indicate that buffer has no more space.
@@ -77,6 +78,8 @@ bool SocketStreamHandleBase::send(const char* data, int length)
void SocketStreamHandleBase::close()
{
+ RefPtr<SocketStreamHandle> protect(static_cast<SocketStreamHandle*>(this)); // platformClose calls the client, which may make the handle get deallocated immediately.
+
platformClose();
m_state = Closed;
}
diff --git a/WebCore/platform/network/SocketStreamHandleClient.h b/WebCore/platform/network/SocketStreamHandleClient.h
index 04c744e..5d97ec0 100644
--- a/WebCore/platform/network/SocketStreamHandleClient.h
+++ b/WebCore/platform/network/SocketStreamHandleClient.h
@@ -43,18 +43,15 @@ namespace WebCore {
public:
virtual ~SocketStreamHandleClient() { }
- virtual void willOpenStream(SocketStreamHandle*, const KURL&) { }
- virtual void willSendData(SocketStreamHandle*, const char* /*data*/, int /*length*/) { }
-
virtual void didOpen(SocketStreamHandle*) { }
virtual void didClose(SocketStreamHandle*) { }
virtual void didReceiveData(SocketStreamHandle*, const char* /*data*/, int /*length*/) { }
virtual void didFail(SocketStreamHandle*, const SocketStreamError&) { }
+ // No authentication for streams per se, but proxy may ask for credentials.
virtual void didReceiveAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&) { }
virtual void didCancelAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&) { }
- virtual void receivedCancellation(SocketStreamHandle*, const AuthenticationChallenge&) { }
};
} // namespace WebCore
diff --git a/WebCore/platform/network/cf/AuthenticationCF.cpp b/WebCore/platform/network/cf/AuthenticationCF.cpp
index bb05a39..93b62a8 100644
--- a/WebCore/platform/network/cf/AuthenticationCF.cpp
+++ b/WebCore/platform/network/cf/AuthenticationCF.cpp
@@ -27,9 +27,9 @@
#include "AuthenticationCF.h"
#include "AuthenticationChallenge.h"
+#include "AuthenticationClient.h"
#include "Credential.h"
#include "ProtectionSpace.h"
-#include "ResourceHandle.h"
#include <CFNetwork/CFURLAuthChallengePriv.h>
#include <CFNetwork/CFURLCredentialPriv.h>
@@ -51,20 +51,20 @@ AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protecti
}
AuthenticationChallenge::AuthenticationChallenge(CFURLAuthChallengeRef cfChallenge,
- ResourceHandle* sourceHandle)
+ AuthenticationClient* authenticationClient)
: AuthenticationChallengeBase(core(CFURLAuthChallengeGetProtectionSpace(cfChallenge)),
core(CFURLAuthChallengeGetProposedCredential(cfChallenge)),
CFURLAuthChallengeGetPreviousFailureCount(cfChallenge),
(CFURLResponseRef)CFURLAuthChallengeGetFailureResponse(cfChallenge),
CFURLAuthChallengeGetError(cfChallenge))
- , m_sourceHandle(sourceHandle)
+ , m_authenticationClient(authenticationClient)
, m_cfChallenge(cfChallenge)
{
}
bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
{
- if (a.sourceHandle() != b.sourceHandle())
+ if (a.authenticationClient() != b.authenticationClient())
return false;
if (a.cfURLAuthChallengeRef() != b.cfURLAuthChallengeRef())
diff --git a/WebCore/platform/network/cf/AuthenticationChallenge.h b/WebCore/platform/network/cf/AuthenticationChallenge.h
index 9697d7e..58fb836 100644
--- a/WebCore/platform/network/cf/AuthenticationChallenge.h
+++ b/WebCore/platform/network/cf/AuthenticationChallenge.h
@@ -26,29 +26,29 @@
#define AuthenticationChallenge_h
#include "AuthenticationChallengeBase.h"
-#include "ResourceHandle.h"
+#include "AuthenticationClient.h"
#include <wtf/RefPtr.h>
typedef struct _CFURLAuthChallenge* CFURLAuthChallengeRef;
namespace WebCore {
-class ResourceHandle;
-
class AuthenticationChallenge : public AuthenticationChallengeBase {
public:
AuthenticationChallenge() {}
AuthenticationChallenge(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error);
- AuthenticationChallenge(CFURLAuthChallengeRef, ResourceHandle* sourceHandle);
+ AuthenticationChallenge(CFURLAuthChallengeRef, AuthenticationClient*);
+
+ AuthenticationClient* authenticationClient() const { return m_authenticationClient.get(); }
+ void setAuthenticationClient(AuthenticationClient* client) { m_authenticationClient = client; }
- ResourceHandle* sourceHandle() const { return m_sourceHandle.get(); }
CFURLAuthChallengeRef cfURLAuthChallengeRef() const { return m_cfChallenge.get(); }
private:
friend class AuthenticationChallengeBase;
static bool platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b);
- RefPtr<ResourceHandle> m_sourceHandle;
+ RefPtr<AuthenticationClient> m_authenticationClient;
RetainPtr<CFURLAuthChallengeRef> m_cfChallenge;
};
diff --git a/WebCore/platform/network/cf/CredentialStorageCFNet.cpp b/WebCore/platform/network/cf/CredentialStorageCFNet.cpp
new file mode 100644
index 0000000..0a9e36f
--- /dev/null
+++ b/WebCore/platform/network/cf/CredentialStorageCFNet.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CredentialStorage.h"
+
+#include "AuthenticationCF.h"
+#include "Credential.h"
+#include "ProtectionSpace.h"
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#include <wtf/RetainPtr.h>
+
+namespace WebCore {
+
+Credential CredentialStorage::getFromPersistentStorage(const ProtectionSpace& protectionSpace)
+{
+ RetainPtr<CFURLProtectionSpaceRef> protectionSpaceCF(AdoptCF, createCF(protectionSpace));
+ RetainPtr<CFURLCredentialRef> credentialCF(AdoptCF, wkCopyCredentialFromCFPersistentStorage(protectionSpaceCF.get()));
+ return core(credentialCF.get());
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/network/cf/DNSCFNet.cpp b/WebCore/platform/network/cf/DNSCFNet.cpp
index 381dff2..6311baf 100644
--- a/WebCore/platform/network/cf/DNSCFNet.cpp
+++ b/WebCore/platform/network/cf/DNSCFNet.cpp
@@ -33,7 +33,7 @@
#include <wtf/StdLibExtras.h>
#if PLATFORM(WIN)
-#include "ResourceHandle.h" // for loaderRunLoop()
+#include "LoaderRunLoopCF.h"
#endif
#ifdef BUILDING_ON_TIGER
@@ -137,7 +137,7 @@ void DNSResolveQueue::resolve(const String& hostname)
CFHostScheduleWithRunLoop(host.get(), CFRunLoopGetMain(), kCFRunLoopCommonModes);
#else
// On Windows, we run a separate thread with CFRunLoop, which is where clientCallback will be called.
- CFHostScheduleWithRunLoop(host.get(), ResourceHandle::loaderRunLoop(), kCFRunLoopDefaultMode);
+ CFHostScheduleWithRunLoop(host.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
#endif
CFHostStartInfoResolution(host.get(), kCFHostAddresses, 0);
host.releaseRef(); // The host will be released from clientCallback().
diff --git a/WebCore/platform/network/cf/LoaderRunLoopCF.cpp b/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
new file mode 100644
index 0000000..aa68916
--- /dev/null
+++ b/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LoaderRunLoopCF.h"
+
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+static CFRunLoopRef loaderRunLoopObject = 0;
+
+static void emptyPerform(void*)
+{
+}
+
+static void* runLoaderThread(void*)
+{
+ loaderRunLoopObject = CFRunLoopGetCurrent();
+
+ // Must add a source to the run loop to prevent CFRunLoopRun() from exiting.
+ CFRunLoopSourceContext ctxt = {0, (void*)1 /*must be non-NULL*/, 0, 0, 0, 0, 0, 0, 0, emptyPerform};
+ CFRunLoopSourceRef bogusSource = CFRunLoopSourceCreate(0, 0, &ctxt);
+ CFRunLoopAddSource(loaderRunLoopObject, bogusSource, kCFRunLoopDefaultMode);
+
+ CFRunLoopRun();
+
+ return 0;
+}
+
+CFRunLoopRef loaderRunLoop()
+{
+ ASSERT(isMainThread());
+ if (!loaderRunLoopObject) {
+ createThread(runLoaderThread, 0, "WebCore: CFNetwork Loader");
+ while (!loaderRunLoopObject) {
+ // FIXME: Sleep 10? that can't be right...
+ Sleep(10);
+ }
+ }
+ return loaderRunLoopObject;
+}
+
+}
diff --git a/WebCore/platform/network/cf/LoaderRunLoopCF.h b/WebCore/platform/network/cf/LoaderRunLoopCF.h
new file mode 100644
index 0000000..20e4c29
--- /dev/null
+++ b/WebCore/platform/network/cf/LoaderRunLoopCF.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LoaderRunLoopCF_h
+#define LoaderRunLoopCF_h
+
+#if !PLATFORM(WIN)
+#error This code is not needed on platforms other than Windows, because main thread's CFRunLoop can be used.
+#endif
+
+namespace WebCore {
+
+CFRunLoopRef loaderRunLoop();
+
+}
+
+#endif // LoaderRunLoop_h
diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index 38a9705..8cc5022 100644
--- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -39,6 +39,7 @@
#include "FormDataStreamCFNet.h"
#include "Frame.h"
#include "FrameLoader.h"
+#include "LoaderRunLoopCF.h"
#include "Logging.h"
#include "MIMETypeRegistry.h"
#include "ResourceError.h"
@@ -322,37 +323,6 @@ CFArrayRef arrayFromFormData(const FormData& d)
return a;
}
-void emptyPerform(void* unused)
-{
-}
-
-static CFRunLoopRef loaderRL = 0;
-void* runLoaderThread(void *unused)
-{
- loaderRL = CFRunLoopGetCurrent();
-
- // Must add a source to the run loop to prevent CFRunLoopRun() from exiting
- CFRunLoopSourceContext ctxt = {0, (void *)1 /*must be non-NULL*/, 0, 0, 0, 0, 0, 0, 0, emptyPerform};
- CFRunLoopSourceRef bogusSource = CFRunLoopSourceCreate(0, 0, &ctxt);
- CFRunLoopAddSource(loaderRL, bogusSource,kCFRunLoopDefaultMode);
-
- CFRunLoopRun();
-
- return 0;
-}
-
-CFRunLoopRef ResourceHandle::loaderRunLoop()
-{
- if (!loaderRL) {
- createThread(runLoaderThread, 0, "WebCore: CFNetwork Loader");
- while (loaderRL == 0) {
- // FIXME: sleep 10? that can't be right...
- Sleep(10);
- }
- }
- return loaderRL;
-}
-
static CFURLRequestRef makeFinalRequest(const ResourceRequest& request, bool shouldContentSniff)
{
CFMutableURLRequestRef newRequest = CFURLRequestCreateMutableCopy(kCFAllocatorDefault, request.cfURLRequest());
@@ -479,11 +449,11 @@ bool ResourceHandle::shouldUseCredentialStorage()
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
LOG(Network, "CFNet - didReceiveAuthenticationChallenge()");
- ASSERT(!d->m_currentCFChallenge);
ASSERT(d->m_currentWebChallenge.isNull());
// Since CFURLConnection networking relies on keeping a reference to the original CFURLAuthChallengeRef,
// we make sure that is actually present
ASSERT(challenge.cfURLAuthChallengeRef());
+ ASSERT(challenge.authenticationClient() == this); // Should be already set.
if (!d->m_user.isNull() && !d->m_pass.isNull()) {
RetainPtr<CFStringRef> user(AdoptCF, d->m_user.createCFString());
@@ -513,8 +483,7 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall
}
}
- d->m_currentCFChallenge = challenge.cfURLAuthChallengeRef();
- d->m_currentWebChallenge = AuthenticationChallenge(d->m_currentCFChallenge, this);
+ d->m_currentWebChallenge = challenge;
if (client())
client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
diff --git a/WebCore/platform/network/cf/ResourceRequest.h b/WebCore/platform/network/cf/ResourceRequest.h
index 8ead412..e361af5 100644
--- a/WebCore/platform/network/cf/ResourceRequest.h
+++ b/WebCore/platform/network/cf/ResourceRequest.h
@@ -34,8 +34,8 @@ typedef const struct _CFURLRequest* CFURLRequestRef;
namespace WebCore {
- struct ResourceRequest : ResourceRequestBase {
-
+ class ResourceRequest : public ResourceRequestBase {
+ public:
ResourceRequest(const String& url)
: ResourceRequestBase(KURL(ParsedURLString, url), UseProtocolCachePolicy)
{
@@ -64,7 +64,7 @@ namespace WebCore {
CFURLRequestRef cfURLRequest() const;
private:
- friend struct ResourceRequestBase;
+ friend class ResourceRequestBase;
void doUpdatePlatformRequest();
void doUpdateResourceRequest();
diff --git a/WebCore/platform/network/cf/ResourceRequestCFNet.h b/WebCore/platform/network/cf/ResourceRequestCFNet.h
index d26072d..e9ebe76 100644
--- a/WebCore/platform/network/cf/ResourceRequestCFNet.h
+++ b/WebCore/platform/network/cf/ResourceRequestCFNet.h
@@ -30,7 +30,7 @@ typedef const struct _CFURLRequest* CFURLRequestRef;
namespace WebCore {
- struct ResourceRequest;
+ class ResourceRequest;
void getResourceRequest(ResourceRequest&, CFURLRequestRef);
CFURLRequestRef cfURLRequest(const ResourceRequest&);
diff --git a/WebCore/platform/network/cf/SocketStreamHandle.h b/WebCore/platform/network/cf/SocketStreamHandle.h
index 64139e5..63bf9a7 100644
--- a/WebCore/platform/network/cf/SocketStreamHandle.h
+++ b/WebCore/platform/network/cf/SocketStreamHandle.h
@@ -32,10 +32,9 @@
#ifndef SocketStreamHandle_h
#define SocketStreamHandle_h
+#include "AuthenticationClient.h"
#include "SocketStreamHandleBase.h"
-
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
namespace WebCore {
@@ -43,24 +42,69 @@ namespace WebCore {
class Credential;
class SocketStreamHandleClient;
- class SocketStreamHandle : public RefCounted<SocketStreamHandle>, public SocketStreamHandleBase {
+ class SocketStreamHandle : public RefCounted<SocketStreamHandle>, public SocketStreamHandleBase, public AuthenticationClient {
public:
static PassRefPtr<SocketStreamHandle> create(const KURL& url, SocketStreamHandleClient* client) { return adoptRef(new SocketStreamHandle(url, client)); }
virtual ~SocketStreamHandle();
- protected:
+ using RefCounted<SocketStreamHandle>::ref;
+ using RefCounted<SocketStreamHandle>::deref;
+
+ private:
virtual int platformSend(const char* data, int length);
virtual void platformClose();
- private:
SocketStreamHandle(const KURL&, SocketStreamHandleClient*);
+ void createStreams();
+ void scheduleStreams();
+ void chooseProxy();
+#ifndef BUILDING_ON_TIGER
+ void chooseProxyFromArray(CFArrayRef);
+ void executePACFileURL(CFURLRef);
+ void removePACRunLoopSource();
+ RetainPtr<CFRunLoopSourceRef> m_pacRunLoopSource;
+ static void pacExecutionCallback(void* client, CFArrayRef proxyList, CFErrorRef error);
+ static void pacExecutionCallbackMainThread(void*);
+ static CFStringRef copyPACExecutionDescription(void*);
+#endif
+
+ bool shouldUseSSL() const { return m_url.protocolIs("wss"); }
+
+ void addCONNECTCredentials(CFHTTPMessageRef response);
+
+ static CFStringRef copyCFStreamDescription(void* );
+ static void readStreamCallback(CFReadStreamRef, CFStreamEventType, void*);
+ static void writeStreamCallback(CFWriteStreamRef, CFStreamEventType, void*);
+#if PLATFORM(WIN)
+ static void readStreamCallbackMainThread(void*);
+ static void writeStreamCallbackMainThread(void*);
+#endif
+ void readStreamCallback(CFStreamEventType);
+ void writeStreamCallback(CFStreamEventType);
// No authentication for streams per se, but proxy may ask for credentials.
- void didReceiveAuthenticationChallenge(const AuthenticationChallenge&);
- void receivedCredential(const AuthenticationChallenge&, const Credential&);
- void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&);
- void receivedCancellation(const AuthenticationChallenge&);
+ virtual void receivedCredential(const AuthenticationChallenge&, const Credential&);
+ virtual void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&);
+ virtual void receivedCancellation(const AuthenticationChallenge&);
+
+ virtual void refAuthenticationClient() { ref(); }
+ virtual void derefAuthenticationClient() { deref(); }
+
+ enum ConnectingSubstate { New, ExecutingPACFile, WaitingForCredentials, WaitingForConnect, Connected };
+ ConnectingSubstate m_connectingSubstate;
+
+ enum ConnectionType { Unknown, Direct, SOCKSProxy, CONNECTProxy };
+ ConnectionType m_connectionType;
+ RetainPtr<CFStringRef> m_proxyHost;
+ RetainPtr<CFNumberRef> m_proxyPort;
+
+ RetainPtr<CFHTTPMessageRef> m_proxyResponseMessage;
+ bool m_sentStoredCredentials;
+ RetainPtr<CFReadStreamRef> m_readStream;
+ RetainPtr<CFWriteStreamRef> m_writeStream;
+
+ RetainPtr<CFURLRef> m_httpsURL; // ws(s): replaced with https:
};
} // namespace WebCore
diff --git a/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp b/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
index 6aa33fc..e7e64da 100644
--- a/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
* Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,58 +32,608 @@
#include "config.h"
#include "SocketStreamHandle.h"
-#include "KURL.h"
+#include "Credential.h"
+#include "CredentialStorage.h"
#include "Logging.h"
-#include "NotImplemented.h"
+#include "ProtectionSpace.h"
+#include "SocketStreamError.h"
#include "SocketStreamHandleClient.h"
+#include <wtf/MainThread.h>
+
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+#include <SystemConfiguration/SystemConfiguration.h>
+#endif
+
+#if PLATFORM(WIN)
+#include "LoaderRunLoopCF.h"
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#else
+#include "WebCoreSystemInterface.h"
+#endif
+
+#ifdef BUILDING_ON_TIGER
+#define CFN_EXPORT extern
+#endif
namespace WebCore {
SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient* client)
: SocketStreamHandleBase(url, client)
+ , m_connectingSubstate(New)
+ , m_connectionType(Unknown)
+ , m_sentStoredCredentials(false)
{
LOG(Network, "SocketStreamHandle %p new client %p", this, m_client);
- notImplemented();
+
+ ASSERT(url.protocolIs("ws") || url.protocolIs("wss"));
+
+ if (!m_url.port())
+ m_url.setPort(shouldUseSSL() ? 443 : 80);
+
+ KURL httpsURL(KURL(), "https://" + m_url.host());
+ m_httpsURL.adoptCF(httpsURL.createCFURL());
+
+ createStreams();
+ ASSERT(!m_readStream == !m_writeStream);
+ if (!m_readStream) // Doing asynchronous PAC file processing, streams will be created later.
+ return;
+
+ scheduleStreams();
+}
+
+void SocketStreamHandle::scheduleStreams()
+{
+ ASSERT(m_readStream);
+ ASSERT(m_writeStream);
+
+ CFStreamClientContext clientContext = { 0, this, 0, 0, copyCFStreamDescription };
+ // FIXME: Pass specific events we're interested in instead of -1.
+ CFReadStreamSetClient(m_readStream.get(), static_cast<CFOptionFlags>(-1), readStreamCallback, &clientContext);
+ CFWriteStreamSetClient(m_writeStream.get(), static_cast<CFOptionFlags>(-1), writeStreamCallback, &clientContext);
+
+#if PLATFORM(WIN)
+ CFReadStreamScheduleWithRunLoop(m_readStream.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
+ CFWriteStreamScheduleWithRunLoop(m_writeStream.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
+#else
+ CFReadStreamScheduleWithRunLoop(m_readStream.get(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ CFWriteStreamScheduleWithRunLoop(m_writeStream.get(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+#endif
+
+ CFReadStreamOpen(m_readStream.get());
+ CFWriteStreamOpen(m_writeStream.get());
+
+#ifndef BUILDING_ON_TIGER
+ if (m_pacRunLoopSource)
+ removePACRunLoopSource();
+#endif
+
+ m_connectingSubstate = WaitingForConnect;
+}
+
+#ifndef BUILDING_ON_TIGER
+CFStringRef SocketStreamHandle::copyPACExecutionDescription(void*)
+{
+ return CFSTR("WebSocket proxy PAC file execution");
+}
+
+struct MainThreadPACCallbackInfo {
+ MainThreadPACCallbackInfo(SocketStreamHandle* handle, CFArrayRef proxyList) : handle(handle), proxyList(proxyList) { }
+ SocketStreamHandle* handle;
+ CFArrayRef proxyList;
+};
+
+void SocketStreamHandle::pacExecutionCallback(void* client, CFArrayRef proxyList, CFErrorRef)
+{
+ SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(client);
+ MainThreadPACCallbackInfo info(handle, proxyList);
+ // If we're already on main thread (e.g. on Mac), callOnMainThreadAndWait() will be just a function call.
+ callOnMainThreadAndWait(pacExecutionCallbackMainThread, &info);
+}
+
+void SocketStreamHandle::pacExecutionCallbackMainThread(void* invocation)
+{
+ MainThreadPACCallbackInfo* info = static_cast<MainThreadPACCallbackInfo*>(invocation);
+ ASSERT(info->handle->m_connectingSubstate == ExecutingPACFile);
+ // This time, the array won't have PAC as a first entry.
+ info->handle->chooseProxyFromArray(info->proxyList);
+ info->handle->createStreams();
+ info->handle->scheduleStreams();
+}
+
+void SocketStreamHandle::executePACFileURL(CFURLRef pacFileURL)
+{
+ // CFNetwork returns an empty proxy array for WebScoket schemes, so use m_httpsURL.
+ CFStreamClientContext clientContext = { 0, this, 0, 0, copyPACExecutionDescription };
+ m_pacRunLoopSource.adoptCF(CFNetworkExecuteProxyAutoConfigurationURL(pacFileURL, m_httpsURL.get(), pacExecutionCallback, &clientContext));
+#if PLATFORM(WIN)
+ CFRunLoopAddSource(loaderRunLoop(), m_pacRunLoopSource.get(), kCFRunLoopDefaultMode);
+#else
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), m_pacRunLoopSource.get(), kCFRunLoopCommonModes);
+#endif
+ m_connectingSubstate = ExecutingPACFile;
+}
+
+void SocketStreamHandle::removePACRunLoopSource()
+{
+ ASSERT(m_pacRunLoopSource);
+
+ CFRunLoopSourceInvalidate(m_pacRunLoopSource.get());
+#if PLATFORM(WIN)
+ CFRunLoopRemoveSource(loaderRunLoop(), m_pacRunLoopSource.get(), kCFRunLoopDefaultMode);
+#else
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_pacRunLoopSource.get(), kCFRunLoopCommonModes);
+#endif
+ m_pacRunLoopSource = 0;
+}
+
+void SocketStreamHandle::chooseProxy()
+{
+#ifndef BUILDING_ON_LEOPARD
+ RetainPtr<CFDictionaryRef> proxyDictionary(AdoptCF, CFNetworkCopySystemProxySettings());
+#else
+ // We don't need proxy information often, so there is no need to set up a permanent dynamic store session.
+ RetainPtr<CFDictionaryRef> proxyDictionary(AdoptCF, SCDynamicStoreCopyProxies(0));
+#endif
+
+ // SOCKS or HTTPS (AKA CONNECT) proxies are supported.
+ // WebSocket protocol relies on handshake being transferred unchanged, so we need a proxy that will not modify headers.
+ // Since HTTP proxies must add Via headers, they are highly unlikely to work.
+ // Many CONNECT proxies limit connectivity to port 443, so we prefer SOCKS, if configured.
+
+ if (!proxyDictionary) {
+ m_connectionType = Direct;
+ return;
+ }
+
+ // CFNetworkCopyProxiesForURL doesn't know about WebSocket schemes, so pretend to use http.
+ // Always use "https" to get HTTPS proxies in result - we'll try to use those for ws:// even though many are configured to reject connections to ports other than 443.
+ RetainPtr<CFArrayRef> proxyArray(AdoptCF, CFNetworkCopyProxiesForURL(m_httpsURL.get(), proxyDictionary.get()));
+
+ chooseProxyFromArray(proxyArray.get());
+}
+
+void SocketStreamHandle::chooseProxyFromArray(CFArrayRef proxyArray)
+{
+ if (!proxyArray)
+ m_connectionType = Direct;
+
+ CFIndex proxyArrayCount = CFArrayGetCount(proxyArray);
+
+ // PAC is always the first entry, if present.
+ if (proxyArrayCount) {
+ CFDictionaryRef proxyInfo = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxyArray, 0));
+ CFTypeRef proxyType = CFDictionaryGetValue(proxyInfo, kCFProxyTypeKey);
+ if (proxyType && CFGetTypeID(proxyType) == CFStringGetTypeID()) {
+ if (CFEqual(proxyType, kCFProxyTypeAutoConfigurationURL)) {
+ CFTypeRef pacFileURL = CFDictionaryGetValue(proxyInfo, kCFProxyAutoConfigurationURLKey);
+ if (pacFileURL && CFGetTypeID(pacFileURL) == CFURLGetTypeID()) {
+ executePACFileURL(static_cast<CFURLRef>(pacFileURL));
+ return;
+ }
+ }
+ }
+ }
+
+ CFDictionaryRef chosenProxy = 0;
+ for (CFIndex i = 0; i < proxyArrayCount; ++i) {
+ CFDictionaryRef proxyInfo = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(proxyArray, i));
+ CFTypeRef proxyType = CFDictionaryGetValue(proxyInfo, kCFProxyTypeKey);
+ if (proxyType && CFGetTypeID(proxyType) == CFStringGetTypeID()) {
+ if (CFEqual(proxyType, kCFProxyTypeSOCKS)) {
+ m_connectionType = SOCKSProxy;
+ chosenProxy = proxyInfo;
+ break;
+ }
+ if (CFEqual(proxyType, kCFProxyTypeHTTPS)) {
+ m_connectionType = CONNECTProxy;
+ chosenProxy = proxyInfo;
+ // Keep looking for proxies, as a SOCKS one is preferable.
+ }
+ }
+ }
+
+ if (chosenProxy) {
+ ASSERT(m_connectionType != Unknown);
+ ASSERT(m_connectionType != Direct);
+
+ CFTypeRef proxyHost = CFDictionaryGetValue(chosenProxy, kCFProxyHostNameKey);
+ CFTypeRef proxyPort = CFDictionaryGetValue(chosenProxy, kCFProxyPortNumberKey);
+
+ if (proxyHost && CFGetTypeID(proxyHost) == CFStringGetTypeID() && proxyPort && CFGetTypeID(proxyPort) == CFNumberGetTypeID()) {
+ m_proxyHost = static_cast<CFStringRef>(proxyHost);
+ m_proxyPort = static_cast<CFNumberRef>(proxyPort);
+ return;
+ }
+ }
+
+ m_connectionType = Direct;
+}
+
+#else // BUILDING_ON_TIGER
+
+void SocketStreamHandle::chooseProxy()
+{
+ // We don't need proxy information often, so there is no need to set up a permanent dynamic store session.
+ RetainPtr<CFDictionaryRef> proxyDictionary(AdoptCF, SCDynamicStoreCopyProxies(0));
+
+ // SOCKS or HTTPS (AKA CONNECT) proxies are supported.
+ // WebSocket protocol relies on handshake being transferred unchanged, so we need a proxy that will not modify headers.
+ // Since HTTP proxies must add Via headers, they are highly unlikely to work.
+ // Many CONNECT proxies limit connectivity to port 443, so we prefer SOCKS, if configured.
+
+ if (!proxyDictionary) {
+ m_connectionType = Direct;
+ return;
+ }
+
+ // FIXME: check proxy bypass list and ExcludeSimpleHostnames.
+ // FIXME: Support PAC files.
+
+ CFTypeRef socksEnableCF = CFDictionaryGetValue(proxyDictionary.get(), kSCPropNetProxiesSOCKSEnable);
+ int socksEnable;
+ if (socksEnableCF && CFGetTypeID(socksEnableCF) == CFNumberGetTypeID() && CFNumberGetValue(static_cast<CFNumberRef>(socksEnableCF), kCFNumberIntType, &socksEnable) && socksEnable) {
+ CFTypeRef proxyHost = CFDictionaryGetValue(proxyDictionary.get(), kSCPropNetProxiesSOCKSProxy);
+ CFTypeRef proxyPort = CFDictionaryGetValue(proxyDictionary.get(), kSCPropNetProxiesSOCKSPort);
+ if (proxyHost && CFGetTypeID(proxyHost) == CFStringGetTypeID() && proxyPort && CFGetTypeID(proxyPort) == CFNumberGetTypeID()) {
+ m_proxyHost = static_cast<CFStringRef>(proxyHost);
+ m_proxyPort = static_cast<CFNumberRef>(proxyPort);
+ m_connectionType = SOCKSProxy;
+ return;
+ }
+ }
+
+ CFTypeRef httpsEnableCF = CFDictionaryGetValue(proxyDictionary.get(), kSCPropNetProxiesHTTPSEnable);
+ int httpsEnable;
+ if (httpsEnableCF && CFGetTypeID(httpsEnableCF) == CFNumberGetTypeID() && CFNumberGetValue(static_cast<CFNumberRef>(httpsEnableCF), kCFNumberIntType, &httpsEnable) && httpsEnable) {
+ CFTypeRef proxyHost = CFDictionaryGetValue(proxyDictionary.get(), kSCPropNetProxiesHTTPSProxy);
+ CFTypeRef proxyPort = CFDictionaryGetValue(proxyDictionary.get(), kSCPropNetProxiesHTTPSPort);
+
+ if (proxyHost && CFGetTypeID(proxyHost) == CFStringGetTypeID() && proxyPort && CFGetTypeID(proxyPort) == CFNumberGetTypeID()) {
+ m_proxyHost = static_cast<CFStringRef>(proxyHost);
+ m_proxyPort = static_cast<CFNumberRef>(proxyPort);
+ m_connectionType = CONNECTProxy;
+ return;
+ }
+ }
+
+ m_connectionType = Direct;
+}
+#endif // BUILDING_ON_TIGER
+
+void SocketStreamHandle::createStreams()
+{
+ if (m_connectionType == Unknown)
+ chooseProxy();
+
+ // If it's still unknown, then we're resolving a PAC file asynchronously.
+ if (m_connectionType == Unknown)
+ return;
+
+ RetainPtr<CFStringRef> host(AdoptCF, m_url.host().createCFString());
+
+ // Creating streams to final destination, not to proxy.
+ CFReadStreamRef readStream = 0;
+ CFWriteStreamRef writeStream = 0;
+ CFStreamCreatePairWithSocketToHost(0, host.get(), m_url.port(), &readStream, &writeStream);
+
+ m_readStream.adoptCF(readStream);
+ m_writeStream.adoptCF(writeStream);
+
+ switch (m_connectionType) {
+ case Unknown:
+ ASSERT_NOT_REACHED();
+ break;
+ case Direct:
+ break;
+ case SOCKSProxy: {
+ // FIXME: SOCKS5 doesn't do challenge-response, should we try to apply credentials from Keychain right away?
+ // But SOCKS5 credentials don't work at the time of this writing anyway, see <rdar://6776698>.
+ const void* proxyKeys[] = { kCFStreamPropertySOCKSProxyHost, kCFStreamPropertySOCKSProxyPort };
+ const void* proxyValues[] = { m_proxyHost.get(), m_proxyPort.get() };
+ RetainPtr<CFDictionaryRef> connectDictionary(AdoptCF, CFDictionaryCreate(0, proxyKeys, proxyValues, sizeof(proxyKeys) / sizeof(*proxyKeys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ CFReadStreamSetProperty(m_readStream.get(), kCFStreamPropertySOCKSProxy, connectDictionary.get());
+ break;
+ }
+ case CONNECTProxy:
+ wkSetCONNECTProxyForStream(m_readStream.get(), m_proxyHost.get(), m_proxyPort.get());
+ break;
+ }
+
+ if (shouldUseSSL()) {
+ const void* keys[] = { kCFStreamSSLPeerName, kCFStreamSSLLevel };
+ const void* values[] = { host.get(), kCFStreamSocketSecurityLevelNegotiatedSSL };
+ RetainPtr<CFDictionaryRef> settings(AdoptCF, CFDictionaryCreate(0, keys, values, sizeof(keys) / sizeof(*keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ CFReadStreamSetProperty(m_readStream.get(), kCFStreamPropertySSLSettings, settings.get());
+ CFWriteStreamSetProperty(m_writeStream.get(), kCFStreamPropertySSLSettings, settings.get());
+ }
+}
+
+static bool getStoredCONNECTProxyCredentials(const ProtectionSpace& protectionSpace, String& login, String& password)
+{
+ // Try system credential storage first, matching HTTP behavior (CFNetwork only asks the client for password if it couldn't find it in Keychain).
+ Credential storedCredential = CredentialStorage::getFromPersistentStorage(protectionSpace);
+ if (storedCredential.isEmpty())
+ storedCredential = CredentialStorage::get(protectionSpace);
+
+ if (storedCredential.isEmpty())
+ return false;
+
+ login = storedCredential.user();
+ password = storedCredential.password();
+
+ return true;
+}
+
+static ProtectionSpaceAuthenticationScheme authenticationSchemeFromAuthenticationMethod(CFStringRef method)
+{
+ if (CFEqual(method, kCFHTTPAuthenticationSchemeBasic))
+ return ProtectionSpaceAuthenticationSchemeHTTPBasic;
+ if (CFEqual(method, kCFHTTPAuthenticationSchemeDigest))
+ return ProtectionSpaceAuthenticationSchemeHTTPDigest;
+#ifndef BUILDING_ON_TIGER
+ if (CFEqual(method, kCFHTTPAuthenticationSchemeNTLM))
+ return ProtectionSpaceAuthenticationSchemeNTLM;
+ if (CFEqual(method, kCFHTTPAuthenticationSchemeNegotiate))
+ return ProtectionSpaceAuthenticationSchemeNegotiate;
+#endif
+ ASSERT_NOT_REACHED();
+ return ProtectionSpaceAuthenticationSchemeDefault;
+}
+
+void SocketStreamHandle::addCONNECTCredentials(CFHTTPMessageRef proxyResponse)
+{
+ RetainPtr<CFHTTPAuthenticationRef> authentication(AdoptCF, CFHTTPAuthenticationCreateFromResponse(0, proxyResponse));
+
+ if (!CFHTTPAuthenticationRequiresUserNameAndPassword(authentication.get())) {
+ // That's all we can offer...
+ m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error.
+ return;
+ }
+
+ int port = 0;
+ CFNumberGetValue(m_proxyPort.get(), kCFNumberIntType, &port);
+ RetainPtr<CFStringRef> methodCF(AdoptCF, CFHTTPAuthenticationCopyMethod(authentication.get()));
+ RetainPtr<CFStringRef> realmCF(AdoptCF, CFHTTPAuthenticationCopyRealm(authentication.get()));
+ ProtectionSpace protectionSpace(String(m_proxyHost.get()), port, ProtectionSpaceProxyHTTPS, String(realmCF.get()), authenticationSchemeFromAuthenticationMethod(methodCF.get()));
+ String login;
+ String password;
+ if (!m_sentStoredCredentials && getStoredCONNECTProxyCredentials(protectionSpace, login, password)) {
+ // Try to apply stored credentials, if we haven't tried those already.
+ RetainPtr<CFStringRef> loginCF(AdoptCF, login.createCFString());
+ RetainPtr<CFStringRef> passwordCF(AdoptCF, password.createCFString());
+ // Creating a temporary request to make CFNetwork apply credentials to it. Unfortunately, this cannot work with NTLM authentication.
+ RetainPtr<CFHTTPMessageRef> dummyRequest(AdoptCF, CFHTTPMessageCreateRequest(0, CFSTR("GET"), m_httpsURL.get(), kCFHTTPVersion1_1));
+
+ Boolean appliedCredentials = CFHTTPMessageApplyCredentials(dummyRequest.get(), authentication.get(), loginCF.get(), passwordCF.get(), 0);
+ ASSERT_UNUSED(appliedCredentials, appliedCredentials);
+
+ RetainPtr<CFStringRef> proxyAuthorizationString(AdoptCF, CFHTTPMessageCopyHeaderFieldValue(dummyRequest.get(), CFSTR("Proxy-Authorization")));
+
+ if (!proxyAuthorizationString) {
+ // Fails e.g. for NTLM auth.
+ m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error.
+ return;
+ }
+
+ // Setting the authorization results in a new connection attempt.
+ wkSetCONNECTProxyAuthorizationForStream(m_readStream.get(), proxyAuthorizationString.get());
+ m_sentStoredCredentials = true;
+ return;
+ }
+
+ // FIXME: Ask the client if credentials could not be found.
+
+ m_client->didFail(this, SocketStreamError()); // FIXME: Provide a sensible error.
+}
+
+CFStringRef SocketStreamHandle::copyCFStreamDescription(void* info)
+{
+ SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(info);
+ return ("WebKit socket stream, " + handle->m_url.string()).createCFString();
+}
+
+struct MainThreadEventCallbackInfo {
+ MainThreadEventCallbackInfo(CFStreamEventType type, SocketStreamHandle* handle) : type(type), handle(handle) { }
+ CFStreamEventType type;
+ SocketStreamHandle* handle;
+};
+
+void SocketStreamHandle::readStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void* clientCallBackInfo)
+{
+ SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(clientCallBackInfo);
+ ASSERT_UNUSED(stream, stream == handle->m_readStream.get());
+#if PLATFORM(WIN)
+ MainThreadEventCallbackInfo info(type, handle);
+ callOnMainThreadAndWait(readStreamCallbackMainThread, &info);
+#else
+ ASSERT(isMainThread());
+ handle->readStreamCallback(type);
+#endif
+}
+
+void SocketStreamHandle::writeStreamCallback(CFWriteStreamRef stream, CFStreamEventType type, void* clientCallBackInfo)
+{
+ SocketStreamHandle* handle = static_cast<SocketStreamHandle*>(clientCallBackInfo);
+ ASSERT_UNUSED(stream, stream == handle->m_writeStream.get());
+#if PLATFORM(WIN)
+ MainThreadEventCallbackInfo info(type, handle);
+ callOnMainThreadAndWait(writeStreamCallbackMainThread, &info);
+#else
+ ASSERT(isMainThread());
+ handle->writeStreamCallback(type);
+#endif
+}
+
+#if PLATFORM(WIN)
+void SocketStreamHandle::readStreamCallbackMainThread(void* invocation)
+{
+ MainThreadEventCallbackInfo* info = static_cast<MainThreadEventCallbackInfo*>(invocation);
+ info->handle->readStreamCallback(info->type);
+}
+
+void SocketStreamHandle::writeStreamCallbackMainThread(void* invocation)
+{
+ MainThreadEventCallbackInfo* info = static_cast<MainThreadEventCallbackInfo*>(invocation);
+ info->handle->writeStreamCallback(info->type);
+}
+#endif // PLATFORM(WIN)
+
+void SocketStreamHandle::readStreamCallback(CFStreamEventType type)
+{
+ switch(type) {
+ case kCFStreamEventNone:
+ break;
+ case kCFStreamEventOpenCompleted:
+ break;
+ case kCFStreamEventHasBytesAvailable: {
+ if (m_connectingSubstate == WaitingForConnect) {
+ if (m_connectionType == CONNECTProxy) {
+ RetainPtr<CFHTTPMessageRef> proxyResponse(AdoptCF, wkCopyCONNECTProxyResponse(m_readStream.get(), m_httpsURL.get()));
+ if (proxyResponse && (407 == CFHTTPMessageGetResponseStatusCode(proxyResponse.get()))) {
+ addCONNECTCredentials(proxyResponse.get());
+ return;
+ }
+ }
+ } else if (m_connectingSubstate == WaitingForCredentials)
+ break;
+
+ if (m_connectingSubstate == WaitingForConnect) {
+ m_connectingSubstate = Connected;
+ m_state = Open;
+
+ RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
+ m_client->didOpen(this);
+ if (m_state == Closed)
+ break;
+ // Fall through.
+ } else if (m_state == Closed)
+ break;
+
+ ASSERT(m_state == Open);
+ ASSERT(m_connectingSubstate == Connected);
+
+ CFIndex length;
+ UInt8 localBuffer[1024]; // Used if CFReadStreamGetBuffer couldn't return anything.
+ const UInt8* ptr = CFReadStreamGetBuffer(m_readStream.get(), 0, &length);
+ if (!ptr) {
+ length = CFReadStreamRead(m_readStream.get(), localBuffer, sizeof(localBuffer));
+ ptr = localBuffer;
+ }
+
+ m_client->didReceiveData(this, reinterpret_cast<const char*>(ptr), length);
+
+ break;
+ }
+ case kCFStreamEventCanAcceptBytes:
+ ASSERT_NOT_REACHED();
+ break;
+ case kCFStreamEventErrorOccurred: {
+ CFStreamError error = CFReadStreamGetError(m_readStream.get());
+ m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
+ break;
+ }
+ case kCFStreamEventEndEncountered:
+ platformClose();
+ break;
+ }
+}
+
+void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
+{
+ switch(type) {
+ case kCFStreamEventNone:
+ break;
+ case kCFStreamEventOpenCompleted:
+ break;
+ case kCFStreamEventHasBytesAvailable:
+ ASSERT_NOT_REACHED();
+ break;
+ case kCFStreamEventCanAcceptBytes: {
+ // Possibly, a spurious event from CONNECT handshake.
+ if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
+ return;
+
+ if (m_connectingSubstate == WaitingForCredentials)
+ break;
+
+ if (m_connectingSubstate == WaitingForConnect) {
+ m_connectingSubstate = Connected;
+ m_state = Open;
+
+ RefPtr<SocketStreamHandle> protect(this); // The client can close the handle, potentially removing the last reference.
+ m_client->didOpen(this);
+ break;
+ }
+
+ ASSERT(m_state = Open);
+ ASSERT(m_connectingSubstate == Connected);
+
+ sendPendingData();
+ break;
+ }
+ case kCFStreamEventErrorOccurred: {
+ CFStreamError error = CFWriteStreamGetError(m_writeStream.get());
+ m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
+ break;
+ }
+ case kCFStreamEventEndEncountered:
+ // FIXME: Currently, we handle closing in read callback, but these can come independently (e.g. a server can stop listening, but keep sending data).
+ break;
+ }
}
SocketStreamHandle::~SocketStreamHandle()
{
- LOG(Network, "SocketStreamHandle %p delete", this);
- setClient(0);
- notImplemented();
+ LOG(Network, "SocketStreamHandle %p dtor", this);
+
+#ifndef BUILDING_ON_TIGER
+ ASSERT(!m_pacRunLoopSource);
+#endif
}
-int SocketStreamHandle::platformSend(const char*, int)
+int SocketStreamHandle::platformSend(const char* data, int length)
{
- LOG(Network, "SocketStreamHandle %p platformSend", this);
- notImplemented();
- return 0;
+ if (!CFWriteStreamCanAcceptBytes(m_writeStream.get()))
+ return 0;
+
+ return CFWriteStreamWrite(m_writeStream.get(), reinterpret_cast<const UInt8*>(data), length);
}
void SocketStreamHandle::platformClose()
{
LOG(Network, "SocketStreamHandle %p platformClose", this);
- notImplemented();
-}
-void SocketStreamHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&)
-{
- notImplemented();
+#ifndef BUILDING_ON_TIGER
+ if (m_pacRunLoopSource)
+ removePACRunLoopSource();
+#endif
+
+ ASSERT(!m_readStream == !m_writeStream);
+ if (!m_readStream)
+ return;
+
+ CFReadStreamUnscheduleFromRunLoop(m_readStream.get(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ CFWriteStreamUnscheduleFromRunLoop(m_writeStream.get(), CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+
+ CFReadStreamClose(m_readStream.get());
+ CFWriteStreamClose(m_writeStream.get());
+
+ m_readStream = 0;
+ m_writeStream = 0;
+
+ m_client->didClose(this);
}
void SocketStreamHandle::receivedCredential(const AuthenticationChallenge&, const Credential&)
{
- notImplemented();
}
void SocketStreamHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&)
{
- notImplemented();
}
void SocketStreamHandle::receivedCancellation(const AuthenticationChallenge&)
{
- notImplemented();
}
} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/AuthenticationChallenge.h b/WebCore/platform/network/chromium/AuthenticationChallenge.h
index cd1b430..e2d1f42 100644
--- a/WebCore/platform/network/chromium/AuthenticationChallenge.h
+++ b/WebCore/platform/network/chromium/AuthenticationChallenge.h
@@ -28,25 +28,23 @@
#define AuthenticationChallenge_h
#include "AuthenticationChallengeBase.h"
-#include "ResourceHandle.h"
+#include "AuthenticationClient.h"
#include <wtf/RefPtr.h>
namespace WebCore {
- class ResourceHandle;
-
class AuthenticationChallenge : public AuthenticationChallengeBase {
public:
AuthenticationChallenge() {}
AuthenticationChallenge(const ProtectionSpace&, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse&, const ResourceError&);
- ResourceHandle* sourceHandle() const { return m_sourceHandle.get(); }
+ AuthenticationClient* authenticationClient() const { return m_authenticationClient.get(); }
private:
friend class AuthenticationChallengeBase;
static bool platformCompare(const AuthenticationChallenge&, const AuthenticationChallenge&);
- RefPtr<ResourceHandle> m_sourceHandle;
+ RefPtr<AuthenticationClient> m_authenticationClient;
};
} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/CookieJarChromium.cpp b/WebCore/platform/network/chromium/CookieJarChromium.cpp
index 7862cc3..279d9b0 100644
--- a/WebCore/platform/network/chromium/CookieJarChromium.cpp
+++ b/WebCore/platform/network/chromium/CookieJarChromium.cpp
@@ -53,16 +53,14 @@ bool cookiesEnabled(const Document*)
return true;
}
-bool getRawCookies(const Document*, const KURL&, Vector<Cookie>& rawCookies)
+bool getRawCookies(const Document* document, const KURL& url, Vector<Cookie>& rawCookies)
{
- // FIXME: Not yet implemented
- rawCookies.clear();
- return false; // return true when implemented
+ return ChromiumBridge::rawCookies(url, document->firstPartyForCookies(), &rawCookies);
}
-void deleteCookie(const Document*, const KURL&, const String&)
+void deleteCookie(const Document*, const KURL& url, const String& cookieName)
{
- // FIXME: Not yet implemented
+ return ChromiumBridge::deleteCookie(url, cookieName);
}
} // namespace WebCore
diff --git a/WebCore/platform/network/chromium/ResourceRequest.cpp b/WebCore/platform/network/chromium/ResourceRequest.cpp
index 76d1288..5b27c1b 100644
--- a/WebCore/platform/network/chromium/ResourceRequest.cpp
+++ b/WebCore/platform/network/chromium/ResourceRequest.cpp
@@ -23,6 +23,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include "config.h"
+#include "ResourceRequest.h"
+
namespace WebCore {
// This is used by the loader to control the number of issued parallel load requests.
diff --git a/WebCore/platform/network/chromium/ResourceRequest.h b/WebCore/platform/network/chromium/ResourceRequest.h
index 48ff1e7..176f923 100644
--- a/WebCore/platform/network/chromium/ResourceRequest.h
+++ b/WebCore/platform/network/chromium/ResourceRequest.h
@@ -35,22 +35,13 @@ namespace WebCore {
class Frame;
- struct ResourceRequest : public ResourceRequestBase {
+ class ResourceRequest : public ResourceRequestBase {
public:
- enum TargetType {
- TargetIsMainFrame,
- TargetIsSubFrame,
- TargetIsSubResource,
- TargetIsObject,
- TargetIsMedia
- };
-
ResourceRequest(const String& url)
: ResourceRequestBase(KURL(ParsedURLString, url), UseProtocolCachePolicy)
, m_requestorID(0)
, m_requestorProcessID(0)
, m_appCacheHostID(0)
- , m_targetType(TargetIsSubResource)
{
}
@@ -59,7 +50,6 @@ namespace WebCore {
, m_requestorID(0)
, m_requestorProcessID(0)
, m_appCacheHostID(0)
- , m_targetType(TargetIsSubResource)
, m_securityInfo(securityInfo)
{
}
@@ -69,7 +59,6 @@ namespace WebCore {
, m_requestorID(0)
, m_requestorProcessID(0)
, m_appCacheHostID(0)
- , m_targetType(TargetIsSubResource)
{
}
@@ -78,7 +67,6 @@ namespace WebCore {
, m_requestorID(0)
, m_requestorProcessID(0)
, m_appCacheHostID(0)
- , m_targetType(TargetIsSubResource)
{
setHTTPReferrer(referrer);
}
@@ -88,7 +76,6 @@ namespace WebCore {
, m_requestorID(0)
, m_requestorProcessID(0)
, m_appCacheHostID(0)
- , m_targetType(TargetIsSubResource)
{
}
@@ -96,10 +83,6 @@ namespace WebCore {
int requestorID() const { return m_requestorID; }
void setRequestorID(int requestorID) { m_requestorID = requestorID; }
- // What this request is for.
- TargetType targetType() const { return m_targetType; }
- void setTargetType(TargetType type) { m_targetType = type; }
-
// The process id of the process from which this request originated. In
// the case of out-of-process plugins, this allows to link back the
// request to the plugin process (as it is processed through a render
@@ -129,7 +112,6 @@ namespace WebCore {
int m_requestorID;
int m_requestorProcessID;
int m_appCacheHostID;
- TargetType m_targetType;
CString m_securityInfo;
};
diff --git a/WebCore/platform/network/curl/AuthenticationChallenge.h b/WebCore/platform/network/curl/AuthenticationChallenge.h
index a64d575..7ace096 100644
--- a/WebCore/platform/network/curl/AuthenticationChallenge.h
+++ b/WebCore/platform/network/curl/AuthenticationChallenge.h
@@ -26,13 +26,11 @@
#define AuthenticationChallenge_h
#include "AuthenticationChallengeBase.h"
-#include "ResourceHandle.h"
+#include "AuthenticationClient.h"
#include <wtf/RefPtr.h>
namespace WebCore {
-class ResourceHandle;
-
class AuthenticationChallenge : public AuthenticationChallengeBase {
public:
AuthenticationChallenge()
@@ -44,9 +42,9 @@ public:
{
}
- ResourceHandle* sourceHandle() const { return m_sourceHandle.get(); }
+ AuthenticationClient* authenticationClient() const { return m_authenticationClient.get(); }
- RefPtr<ResourceHandle> m_sourceHandle;
+ RefPtr<AuthenticationClient> m_authenticationClient;
};
}
diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp
index d8a812f..a006a14 100644
--- a/WebCore/platform/network/curl/ResourceHandleManager.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp
@@ -49,6 +49,11 @@
#include <wtf/Threading.h>
#include <wtf/Vector.h>
+#if !PLATFORM(WIN_OS)
+#include <sys/param.h>
+#define MAX_PATH MAXPATHLEN
+#endif
+
namespace WebCore {
const int selectTimeoutMS = 5;
diff --git a/WebCore/platform/network/curl/ResourceRequest.h b/WebCore/platform/network/curl/ResourceRequest.h
index 3fa2795..40e1e8f 100644
--- a/WebCore/platform/network/curl/ResourceRequest.h
+++ b/WebCore/platform/network/curl/ResourceRequest.h
@@ -33,8 +33,8 @@ typedef const struct _CFURLRequest* CFURLRequestRef;
namespace WebCore {
- struct ResourceRequest : ResourceRequestBase {
-
+ class ResourceRequest : public ResourceRequestBase {
+ public:
ResourceRequest(const String& url)
: ResourceRequestBase(KURL(ParsedURLString, url), UseProtocolCachePolicy)
{
diff --git a/WebCore/platform/network/mac/AuthenticationChallenge.h b/WebCore/platform/network/mac/AuthenticationChallenge.h
index e8f3a2d..d74a92c 100644
--- a/WebCore/platform/network/mac/AuthenticationChallenge.h
+++ b/WebCore/platform/network/mac/AuthenticationChallenge.h
@@ -37,21 +37,25 @@ class NSURLAuthenticationChallenge;
namespace WebCore {
+class AuthenticationClient;
+
class AuthenticationChallenge : public AuthenticationChallengeBase {
public:
- AuthenticationChallenge() {}
+ AuthenticationChallenge() { }
AuthenticationChallenge(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error);
AuthenticationChallenge(NSURLAuthenticationChallenge *);
id sender() const { return m_sender.get(); }
- NSURLAuthenticationChallenge *nsURLAuthenticationChallenge() const { return m_macChallenge.get(); }
+ NSURLAuthenticationChallenge *nsURLAuthenticationChallenge() const { return m_nsChallenge.get(); }
+
+ void setAuthenticationClient(AuthenticationClient*); // Changes sender to one that invokes client methods.
private:
friend class AuthenticationChallengeBase;
static bool platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b);
- RetainPtr<id> m_sender;
- RetainPtr<NSURLAuthenticationChallenge *> m_macChallenge;
+ RetainPtr<id> m_sender; // Always the same as [m_macChallenge.get() sender], cached here for performance.
+ RetainPtr<NSURLAuthenticationChallenge *> m_nsChallenge;
};
}
diff --git a/WebCore/platform/network/mac/AuthenticationMac.mm b/WebCore/platform/network/mac/AuthenticationMac.mm
index 93725d5..ea06ecd 100644
--- a/WebCore/platform/network/mac/AuthenticationMac.mm
+++ b/WebCore/platform/network/mac/AuthenticationMac.mm
@@ -26,6 +26,7 @@
#import "AuthenticationMac.h"
#import "AuthenticationChallenge.h"
+#import "AuthenticationClient.h"
#import "Credential.h"
#import "ProtectionSpace.h"
@@ -33,6 +34,51 @@
#import <Foundation/NSURLCredential.h>
#import <Foundation/NSURLProtectionSpace.h>
+using namespace WebCore;
+
+@interface WebCoreAuthenticationClientAsChallengeSender : NSObject <NSURLAuthenticationChallengeSender>
+{
+ AuthenticationClient* m_client;
+}
+- (id)initWithAuthenticationClient:(AuthenticationClient*)client;
+- (void)detachClient;
+@end
+
+@implementation WebCoreAuthenticationClientAsChallengeSender
+
+- (id)initWithAuthenticationClient:(AuthenticationClient*)client
+{
+ self = [self init];
+ if (!self)
+ return nil;
+ m_client = client;
+ return self;
+}
+
+- (void)detachClient
+{
+ m_client = 0;
+}
+
+- (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ if (m_client)
+ m_client->receivedCredential(core(challenge), core(credential));
+}
+
+- (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ if (m_client)
+ m_client->receivedRequestToContinueWithoutCredential(core(challenge));
+}
+
+- (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ if (m_client)
+ m_client->receivedCancellation(core(challenge));
+}
+
+@end
namespace WebCore {
@@ -49,17 +95,28 @@ AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protecti
{
}
-AuthenticationChallenge::AuthenticationChallenge(NSURLAuthenticationChallenge *macChallenge)
- : AuthenticationChallengeBase(core([macChallenge protectionSpace]),
- core([macChallenge proposedCredential]),
- [macChallenge previousFailureCount],
- [macChallenge failureResponse],
- [macChallenge error])
- , m_sender([macChallenge sender])
- , m_macChallenge(macChallenge)
+AuthenticationChallenge::AuthenticationChallenge(NSURLAuthenticationChallenge *challenge)
+ : AuthenticationChallengeBase(core([challenge protectionSpace]),
+ core([challenge proposedCredential]),
+ [challenge previousFailureCount],
+ [challenge failureResponse],
+ [challenge error])
+ , m_sender([challenge sender])
+ , m_nsChallenge(challenge)
{
}
+void AuthenticationChallenge::setAuthenticationClient(AuthenticationClient* client)
+{
+ if (client) {
+ m_sender.adoptNS([[WebCoreAuthenticationClientAsChallengeSender alloc] initWithAuthenticationClient:client]);
+ m_nsChallenge.adoptNS([[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:m_nsChallenge.get() sender:m_sender.get()]);
+ } else {
+ if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
+ [(WebCoreAuthenticationClientAsChallengeSender *)m_sender.get() detachClient];
+ }
+}
+
bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
{
if (a.sender() != b.sender())
@@ -131,6 +188,11 @@ NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace)
case ProtectionSpaceAuthenticationSchemeHTMLForm:
method = NSURLAuthenticationMethodHTMLForm;
break;
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ case ProtectionSpaceAuthenticationSchemeNTLM:
+ method = NSURLAuthenticationMethodNTLM;
+ break;
+#endif
default:
ASSERT_NOT_REACHED();
}
@@ -167,6 +229,15 @@ NSURLCredential *mac(const Credential& coreCredential)
ASSERT_NOT_REACHED();
}
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ if (coreCredential.type() == CredentialTypeClientCertificate) {
+ return [[[NSURLCredential alloc] initWithIdentity:coreCredential.identity()
+ certificates:(NSArray *)coreCredential.certificates()
+ persistence:persistence]
+ autorelease];
+ }
+#endif
+
return [[[NSURLCredential alloc] initWithUser:coreCredential.user()
password:coreCredential.password()
persistence:persistence]
@@ -218,6 +289,10 @@ ProtectionSpace core(NSURLProtectionSpace *macSpace)
scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest;
else if ([method isEqualToString:NSURLAuthenticationMethodHTMLForm])
scheme = ProtectionSpaceAuthenticationSchemeHTMLForm;
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ else if ([method isEqualToString:NSURLAuthenticationMethodNTLM])
+ scheme = ProtectionSpaceAuthenticationSchemeNTLM;
+#endif
else
ASSERT_NOT_REACHED();
@@ -240,6 +315,12 @@ Credential core(NSURLCredential *macCredential)
default:
ASSERT_NOT_REACHED();
}
+
+#if CERTIFICATE_CREDENTIALS_SUPPORTED
+ SecIdentityRef identity = [macCredential identity];
+ if (identity)
+ return Credential(identity, (CFArrayRef)[macCredential certificates], persistence);
+#endif
return Credential([macCredential user], [macCredential password], persistence);
}
diff --git a/WebCore/platform/network/mac/CredentialStorageMac.mm b/WebCore/platform/network/mac/CredentialStorageMac.mm
new file mode 100644
index 0000000..66e94e9
--- /dev/null
+++ b/WebCore/platform/network/mac/CredentialStorageMac.mm
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CredentialStorage.h"
+
+#include "AuthenticationMac.h"
+#include "Credential.h"
+
+namespace WebCore {
+
+Credential CredentialStorage::getFromPersistentStorage(const ProtectionSpace& protectionSpace)
+{
+ NSURLCredential *credential = [[NSURLCredentialStorage sharedCredentialStorage] defaultCredentialForProtectionSpace:mac(protectionSpace)];
+ return credential ? core(credential) : Credential();
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp b/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp
index c0918a4..2045eb3 100644
--- a/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp
+++ b/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp
@@ -28,10 +28,10 @@
#include <SystemConfiguration/SystemConfiguration.h>
-#ifdef BUILDING_ON_TIGER
-// This function is available on Tiger, but not declared in the CFRunLoop.h header on Tiger.
-extern "C" CFRunLoopRef CFRunLoopGetMain();
-#endif
+#ifdef BUILDING_ON_TIGER
+// This function is available on Tiger, but not declared in the CFRunLoop.h header on Tiger.
+extern "C" CFRunLoopRef CFRunLoopGetMain();
+#endif
namespace WebCore {
diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm
index 3630b30..360425e 100644
--- a/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -55,7 +55,7 @@ typedef int NSInteger;
using namespace WebCore;
-@interface WebCoreResourceHandleAsDelegate : NSObject <NSURLAuthenticationChallengeSender>
+@interface WebCoreResourceHandleAsDelegate : NSObject
{
ResourceHandle* m_handle;
}
@@ -138,6 +138,7 @@ ResourceHandleInternal::~ResourceHandleInternal()
ResourceHandle::~ResourceHandle()
{
releaseDelegate();
+ d->m_currentWebChallenge.setAuthenticationClient(0);
LOG(Network, "Handle %p destroyed", this);
}
@@ -511,10 +512,8 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall
#endif
d->m_currentMacChallenge = challenge.nsURLAuthenticationChallenge();
- NSURLAuthenticationChallenge *webChallenge = [[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:d->m_currentMacChallenge
- sender:(id<NSURLAuthenticationChallengeSender>)delegate()];
- d->m_currentWebChallenge = core(webChallenge);
- [webChallenge release];
+ d->m_currentWebChallenge = core(d->m_currentMacChallenge);
+ d->m_currentWebChallenge.setAuthenticationClient(this);
if (client())
client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge);
@@ -523,8 +522,8 @@ void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChall
void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge)
{
ASSERT(d->m_currentMacChallenge);
+ ASSERT(d->m_currentMacChallenge == challenge.nsURLAuthenticationChallenge());
ASSERT(!d->m_currentWebChallenge.isNull());
- ASSERT(d->m_currentWebChallenge == challenge);
if (client())
client()->didCancelAuthenticationChallenge(this, challenge);
@@ -547,7 +546,7 @@ void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge
// Manage per-session credentials internally, because once NSURLCredentialPersistenceForSession is used, there is no way
// to ignore it for a particular request (short of removing it altogether).
// <rdar://problem/6867598> gallery.me.com is temporarily whitelisted, so that QuickTime plug-in could see the credentials.
- Credential webCredential(credential.user(), credential.password(), CredentialPersistenceNone);
+ Credential webCredential(credential, CredentialPersistenceNone);
KURL urlToStore;
if (challenge.failureResponse().httpStatusCode() == 401)
urlToStore = d->m_request.url();
@@ -868,27 +867,6 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
return newResponse;
}
-- (void)useCredential:(NSURLCredential *)credential forAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
-{
- if (!m_handle)
- return;
- m_handle->receivedCredential(core(challenge), core(credential));
-}
-
-- (void)continueWithoutCredentialForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
-{
- if (!m_handle)
- return;
- m_handle->receivedRequestToContinueWithoutCredential(core(challenge));
-}
-
-- (void)cancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
-{
- if (!m_handle)
- return;
- m_handle->receivedCancellation(core(challenge));
-}
-
@end
#ifndef BUILDING_ON_TIGER
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
index ed5e024..f7bbb9d 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
@@ -21,8 +21,6 @@
#include "config.h"
#include "QNetworkReplyHandler.h"
-#if QT_VERSION >= 0x040400
-
#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
#include "ResourceHandle.h"
@@ -140,10 +138,14 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
m_method = QNetworkAccessManager::PostOperation;
else if (r.httpMethod() == "PUT")
m_method = QNetworkAccessManager::PutOperation;
+#if QT_VERSION >= 0x040600
+ else if (r.httpMethod() == "DELETE")
+ m_method = QNetworkAccessManager::DeleteOperation;
+#endif
else
m_method = QNetworkAccessManager::UnknownOperation;
- m_request = r.toNetworkRequest();
+ m_request = r.toNetworkRequest(m_resourceHandle->getInternal()->m_frame);
if (m_loadMode == LoadNormal)
start();
@@ -255,7 +257,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
if (m_shouldSendResponse)
return;
- if (m_reply->error())
+ if (m_reply->error() && !ignoreHttpError(m_reply, m_responseDataSent))
return;
if (m_responseSent || !m_resourceHandle)
@@ -305,9 +307,15 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
response.setHTTPStatusText(m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData());
// Add remaining headers.
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ foreach (const QNetworkReply::RawHeaderPair& pair, m_reply->rawHeaderPairs()) {
+ response.setHTTPHeaderField(QString::fromAscii(pair.first), QString::fromAscii(pair.second));
+ }
+#else
foreach (const QByteArray& headerName, m_reply->rawHeaderList()) {
response.setHTTPHeaderField(QString::fromAscii(headerName), QString::fromAscii(m_reply->rawHeader(headerName)));
}
+#endif
}
QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
@@ -321,12 +329,13 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
newRequest.setHTTPMethod("GET");
}
+ // Should not set Referer after a redirect from a secure resource to non-secure one.
+ if (!newRequest.url().protocolIs("https") && protocolIs(newRequest.httpReferrer(), "https"))
+ newRequest.clearHTTPReferrer();
+
client->willSendRequest(m_resourceHandle, newRequest, response);
m_redirected = true;
- m_request = newRequest.toNetworkRequest();
-
- ResourceHandleInternal* d = m_resourceHandle->getInternal();
- emit d->m_frame->page()->networkRequestStarted(d->m_frame, &m_request);
+ m_request = newRequest.toNetworkRequest(m_resourceHandle->getInternal()->m_frame);
return;
}
@@ -368,8 +377,6 @@ void QNetworkReplyHandler::start()
QNetworkAccessManager* manager = d->m_frame->page()->networkAccessManager();
- emit d->m_frame->page()->networkRequestStarted(d->m_frame, &m_request);
-
const QUrl url = m_request.url();
const QString scheme = url.scheme();
// Post requests on files and data don't really make sense, but for
@@ -398,6 +405,12 @@ void QNetworkReplyHandler::start()
putDevice->setParent(m_reply);
break;
}
+#if QT_VERSION >= 0x040600
+ case QNetworkAccessManager::DeleteOperation: {
+ m_reply = manager->deleteResource(m_request);
+ break;
+ }
+#endif
case QNetworkAccessManager::UnknownOperation: {
m_reply = 0;
ResourceHandleClient* client = m_resourceHandle->client();
@@ -461,5 +474,3 @@ void QNetworkReplyHandler::sendQueuedItems()
}
#include "moc_QNetworkReplyHandler.cpp"
-
-#endif
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h
index fccc4a6..2171083 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.h
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h
@@ -21,8 +21,6 @@
#include <QObject>
-#if QT_VERSION >= 0x040400
-
#include <QNetworkRequest>
#include <QNetworkAccessManager>
@@ -113,6 +111,4 @@ private:
}
-#endif
-
#endif // QNETWORKREPLYHANDLER_H
diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp
index f4c30c9..09cdefd 100644
--- a/WebCore/platform/network/qt/ResourceHandleQt.cpp
+++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp
@@ -48,13 +48,9 @@
#endif
#include <QCoreApplication>
#include <QUrl>
-#if QT_VERSION >= 0x040400
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
-#else
-#include "qwebnetworkinterface_p.h"
-#endif
namespace WebCore {
@@ -131,24 +127,25 @@ bool ResourceHandle::start(Frame* frame)
if (!page)
return false;
+ if (!(d->m_user.isEmpty() || d->m_pass.isEmpty())) {
+ // If credentials were specified for this request, add them to the url,
+ // so that they will be passed to QNetworkRequest.
+ KURL urlWithCredentials(d->m_request.url());
+ urlWithCredentials.setUser(d->m_user);
+ urlWithCredentials.setPass(d->m_pass);
+ d->m_request.setURL(urlWithCredentials);
+ }
+
getInternal()->m_frame = static_cast<FrameLoaderClientQt*>(frame->loader()->client())->webFrame();
-#if QT_VERSION < 0x040400
- return QWebNetworkManager::self()->add(this, getInternal()->m_frame->page()->d->networkInterface);
-#else
ResourceHandleInternal *d = getInternal();
d->m_job = new QNetworkReplyHandler(this, QNetworkReplyHandler::LoadMode(d->m_defersLoading));
return true;
-#endif
}
void ResourceHandle::cancel()
{
-#if QT_VERSION < 0x040400
- QWebNetworkManager::self()->cancel(this);
-#else
if (d->m_job)
d->m_job->abort();
-#endif
}
bool ResourceHandle::loadsBlocked()
@@ -196,17 +193,17 @@ void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, S
WebCoreSynchronousLoader syncLoader;
ResourceHandle handle(request, &syncLoader, true, false, true);
-#if QT_VERSION < 0x040400
- if (!QWebNetworkManager::self()->add(&handle, QWebNetworkInterface::defaultInterface(), QWebNetworkManager::SynchronousJob)) {
- // FIXME Create a sane ResourceError
- error = ResourceError(String(), -1, String(), String());
- return;
- }
-#else
ResourceHandleInternal *d = handle.getInternal();
+ if (!(d->m_user.isEmpty() || d->m_pass.isEmpty())) {
+ // If credentials were specified for this request, add them to the url,
+ // so that they will be passed to QNetworkRequest.
+ KURL urlWithCredentials(d->m_request.url());
+ urlWithCredentials.setUser(d->m_user);
+ urlWithCredentials.setPass(d->m_pass);
+ d->m_request.setURL(urlWithCredentials);
+ }
d->m_frame = static_cast<FrameLoaderClientQt*>(frame->loader()->client())->webFrame();
d->m_job = new QNetworkReplyHandler(&handle, QNetworkReplyHandler::LoadNormal);
-#endif
syncLoader.waitForCompletion();
error = syncLoader.resourceError();
@@ -219,10 +216,8 @@ void ResourceHandle::setDefersLoading(bool defers)
{
d->m_defersLoading = defers;
-#if QT_VERSION >= 0x040400
if (d->m_job)
d->m_job->setLoadMode(QNetworkReplyHandler::LoadMode(defers));
-#endif
}
} // namespace WebCore
diff --git a/WebCore/platform/network/qt/ResourceRequest.h b/WebCore/platform/network/qt/ResourceRequest.h
index 93dacf3..fb69326 100644
--- a/WebCore/platform/network/qt/ResourceRequest.h
+++ b/WebCore/platform/network/qt/ResourceRequest.h
@@ -31,12 +31,13 @@
QT_BEGIN_NAMESPACE
class QNetworkRequest;
+class QObject;
QT_END_NAMESPACE
namespace WebCore {
- struct ResourceRequest : ResourceRequestBase {
-
+ class ResourceRequest : public ResourceRequestBase {
+ public:
ResourceRequest(const String& url)
: ResourceRequestBase(KURL(ParsedURLString, url), UseProtocolCachePolicy)
{
@@ -58,9 +59,7 @@ namespace WebCore {
{
}
-#if QT_VERSION >= 0x040400
- QNetworkRequest toNetworkRequest() const;
-#endif
+ QNetworkRequest toNetworkRequest(QObject* originatingObject) const;
private:
friend class ResourceRequestBase;
diff --git a/WebCore/platform/network/qt/ResourceRequestQt.cpp b/WebCore/platform/network/qt/ResourceRequestQt.cpp
index c8f6ad5..752abfe 100644
--- a/WebCore/platform/network/qt/ResourceRequestQt.cpp
+++ b/WebCore/platform/network/qt/ResourceRequestQt.cpp
@@ -21,24 +21,31 @@
#include "ResourceRequest.h"
#include <qglobal.h>
-#if QT_VERSION >= 0x040400
#include <QNetworkRequest>
#include <QUrl>
namespace WebCore {
-QNetworkRequest ResourceRequest::toNetworkRequest() const
+QNetworkRequest ResourceRequest::toNetworkRequest(QObject* originatingFrame) const
{
QNetworkRequest request;
request.setUrl(url());
+#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
+ request.setOriginatingObject(originatingFrame);
+#endif
const HTTPHeaderMap &headers = httpHeaderFields();
for (HTTPHeaderMap::const_iterator it = headers.begin(), end = headers.end();
it != end; ++it) {
QByteArray name = QString(it->first).toAscii();
QByteArray value = QString(it->second).toAscii();
- request.setRawHeader(name, value);
+ // QNetworkRequest::setRawHeader() would remove the header if the value is null
+ // Make sure to set an empty header instead of null header.
+ if (!value.isNull())
+ request.setRawHeader(name, value);
+ else
+ request.setRawHeader(name, "");
}
switch (cachePolicy()) {
@@ -62,4 +69,3 @@ QNetworkRequest ResourceRequest::toNetworkRequest() const
}
-#endif
diff --git a/WebCore/platform/network/soup/DNSSoup.cpp b/WebCore/platform/network/soup/DNSSoup.cpp
index 1ffe1a0..ce55143 100644
--- a/WebCore/platform/network/soup/DNSSoup.cpp
+++ b/WebCore/platform/network/soup/DNSSoup.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2009 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,13 +27,19 @@
#include "config.h"
#include "DNS.h"
-#include "NotImplemented.h"
+#include "CString.h"
+#include "ResourceHandle.h"
namespace WebCore {
void prefetchDNS(const String& hostname)
{
- notImplemented();
+ #ifdef HAVE_LIBSOUP_2_29_3
+ String uri = "http://"+hostname;
+ SoupURI* soupUri = soup_uri_new(uri.utf8().data());
+ soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupUri);
+ soup_uri_free(soupUri);
+ #endif
}
}
diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index 2177bd2..6367a3e 100644
--- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -200,6 +200,13 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
request.setURL(newURL);
request.setHTTPMethod(msg->method);
fillResponseFromMessage(msg, &response);
+
+ // Should not set Referer after a redirect from a secure resource to non-secure one.
+ if (!request.url().protocolIs("https") && protocolIs(request.httpReferrer(), "https")) {
+ request.clearHTTPReferrer();
+ soup_message_headers_remove(msg->request_headers, "Referer");
+ }
+
if (d->client())
d->client()->willSendRequest(handle, request, response);
}
@@ -686,6 +693,13 @@ static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
g_input_stream_close_finish(d->m_inputStream, res, 0);
cleanupGioOperation(handle.get());
+
+ // The load may have been cancelled, the client may have been
+ // destroyed already. In such cases calling didFinishLoading is a
+ // bad idea.
+ if (d->m_cancelled || !client)
+ return;
+
client->didFinishLoading(handle.get());
}
@@ -866,7 +880,7 @@ static bool startGio(ResourceHandle* handle, KURL url)
// using GIO internally, and providing URIs instead of file paths
url.removeFragmentIdentifier();
url.setQuery(String());
- url.setPort(0);
+ url.removePort();
#if !PLATFORM(WIN_OS)
// we avoid the escaping for local files, because
diff --git a/WebCore/platform/network/soup/ResourceRequest.h b/WebCore/platform/network/soup/ResourceRequest.h
index 42b7baa..8270863 100644
--- a/WebCore/platform/network/soup/ResourceRequest.h
+++ b/WebCore/platform/network/soup/ResourceRequest.h
@@ -33,8 +33,8 @@
namespace WebCore {
- struct ResourceRequest : ResourceRequestBase {
-
+ class ResourceRequest : public ResourceRequestBase {
+ public:
ResourceRequest(const String& url)
: ResourceRequestBase(KURL(ParsedURLString, url), UseProtocolCachePolicy)
{
@@ -66,7 +66,7 @@ namespace WebCore {
void updateFromSoupMessage(SoupMessage* soupMessage);
private:
- friend struct ResourceRequestBase;
+ friend class ResourceRequestBase;
void doUpdatePlatformRequest() {};
void doUpdateResourceRequest() {};
diff --git a/WebCore/platform/network/soup/ResourceResponse.h b/WebCore/platform/network/soup/ResourceResponse.h
index 5fa31a0..ecd9f21 100644
--- a/WebCore/platform/network/soup/ResourceResponse.h
+++ b/WebCore/platform/network/soup/ResourceResponse.h
@@ -44,7 +44,14 @@ public:
{
}
+ ResourceResponse(SoupMessage* soupMessage)
+ : ResourceResponseBase()
+ {
+ updateFromSoupMessage(soupMessage);
+ }
+
SoupMessage* toSoupMessage() const;
+ void updateFromSoupMessage(SoupMessage* soupMessage);
private:
friend class ResourceResponseBase;
diff --git a/WebCore/platform/network/soup/ResourceResponseSoup.cpp b/WebCore/platform/network/soup/ResourceResponseSoup.cpp
index 293577f..caf0b31 100644
--- a/WebCore/platform/network/soup/ResourceResponseSoup.cpp
+++ b/WebCore/platform/network/soup/ResourceResponseSoup.cpp
@@ -22,6 +22,7 @@
#include "ResourceResponse.h"
#include "CString.h"
+#include "GOwnPtr.h"
#include "PlatformString.h"
using namespace std;
@@ -49,4 +50,21 @@ SoupMessage* ResourceResponse::toSoupMessage() const
return soupMessage;
}
+void ResourceResponse::updateFromSoupMessage(SoupMessage* soupMessage)
+{
+ SoupURI* soupURI = soup_message_get_uri(soupMessage);
+ GOwnPtr<gchar> uri(soup_uri_to_string(soupURI, FALSE));
+ m_url = KURL(KURL(), String::fromUTF8(uri.get()));
+
+ m_httpStatusCode = soupMessage->status_code;
+
+ SoupMessageHeadersIter headersIter;
+ const char* headerName;
+ const char* headerValue;
+
+ soup_message_headers_iter_init(&headersIter, soupMessage->response_headers);
+ while (soup_message_headers_iter_next(&headersIter, &headerName, &headerValue))
+ m_httpHeaderFields.set(String::fromUTF8(headerName), String::fromUTF8(headerValue));
+}
+
}