diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 19:30:52 -0800 |
commit | 8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2 (patch) | |
tree | 11425ea0b299d6fb89c6d3618a22d97d5bf68d0f /WebCore/platform/network | |
parent | 648161bb0edfc3d43db63caed5cc5213bc6cb78f (diff) | |
download | external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.zip external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.gz external_webkit-8e35f3cfc7fba1d1c829dc557ebad6409cbe16a2.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'WebCore/platform/network')
95 files changed, 12279 insertions, 0 deletions
diff --git a/WebCore/platform/network/AuthenticationChallengeBase.cpp b/WebCore/platform/network/AuthenticationChallengeBase.cpp new file mode 100644 index 0000000..df80441 --- /dev/null +++ b/WebCore/platform/network/AuthenticationChallengeBase.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "AuthenticationChallenge.h" + +#include "ResourceHandle.h" + +namespace WebCore { + +AuthenticationChallengeBase::AuthenticationChallengeBase() + : m_isNull(true) + , m_previousFailureCount(0) +{ +} + +AuthenticationChallengeBase::AuthenticationChallengeBase(const ProtectionSpace& protectionSpace, + const Credential& proposedCredential, + unsigned previousFailureCount, + const ResourceResponse& response, + const ResourceError& error) + : m_isNull(false) + , m_protectionSpace(protectionSpace) + , m_proposedCredential(proposedCredential) + , m_previousFailureCount(previousFailureCount) + , m_failureResponse(response) + , m_error(error) +{ +} + +unsigned AuthenticationChallengeBase::previousFailureCount() const +{ + return m_previousFailureCount; +} + +const Credential& AuthenticationChallengeBase::proposedCredential() const +{ + return m_proposedCredential; +} + +const ProtectionSpace& AuthenticationChallengeBase::protectionSpace() const +{ + return m_protectionSpace; +} + +const ResourceResponse& AuthenticationChallengeBase::failureResponse() const +{ + return m_failureResponse; +} + +const ResourceError& AuthenticationChallengeBase::error() const +{ + return m_error; +} + +bool AuthenticationChallengeBase::isNull() const +{ + return m_isNull; +} + +void AuthenticationChallengeBase::nullify() +{ + m_isNull = true; +} + +bool AuthenticationChallengeBase::compare(const AuthenticationChallenge& a, const AuthenticationChallenge& b) +{ + if (a.isNull() && b.isNull()) + return true; + + if (a.isNull() || b.isNull()) + return false; + + if (a.protectionSpace() != b.protectionSpace()) + return false; + + if (a.proposedCredential() != b.proposedCredential()) + return false; + + if (a.previousFailureCount() != b.previousFailureCount()) + return false; + + if (a.failureResponse() != b.failureResponse()) + return false; + + if (a.error() != b.error()) + return false; + + return AuthenticationChallenge::platformCompare(a, b); +} + +} diff --git a/WebCore/platform/network/AuthenticationChallengeBase.h b/WebCore/platform/network/AuthenticationChallengeBase.h new file mode 100644 index 0000000..5810a6d --- /dev/null +++ b/WebCore/platform/network/AuthenticationChallengeBase.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationChallengeBase_h +#define AuthenticationChallengeBase_h + +#include "Credential.h" +#include "ProtectionSpace.h" +#include "ResourceResponse.h" +#include "ResourceError.h" + +namespace WebCore { + +class AuthenticationChallenge; + +class AuthenticationChallengeBase { +public: + AuthenticationChallengeBase(); + AuthenticationChallengeBase(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error); + + unsigned previousFailureCount() const; + const Credential& proposedCredential() const; + const ProtectionSpace& protectionSpace() const; + const ResourceResponse& failureResponse() const; + const ResourceError& error() const; + + bool isNull() const; + void nullify(); + + static bool compare(const AuthenticationChallenge& a, const AuthenticationChallenge& b); + +protected: + // The AuthenticationChallenge subclass may "shadow" this method to compare platform specific fields + static bool platformCompare(const AuthenticationChallengeBase& a, const AuthenticationChallengeBase& b) { return true; } + + bool m_isNull; + ProtectionSpace m_protectionSpace; + Credential m_proposedCredential; + unsigned m_previousFailureCount; + ResourceResponse m_failureResponse; + ResourceError m_error; +}; + +inline bool operator==(const AuthenticationChallenge& a, const AuthenticationChallenge& b) { return AuthenticationChallengeBase::compare(a, b); } +inline bool operator!=(const AuthenticationChallenge& a, const AuthenticationChallenge& b) { return !(a == b); } + +} + +#endif diff --git a/WebCore/platform/network/Credential.cpp b/WebCore/platform/network/Credential.cpp new file mode 100644 index 0000000..4743959 --- /dev/null +++ b/WebCore/platform/network/Credential.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "Credential.h" + +namespace WebCore { + +// Need to enforce empty, non-null strings due to the pickiness of the String == String operator +// combined with the semantics of the String(NSString*) constructor +Credential::Credential() + : m_user("") + , m_password("") +{ +} + +// Need to enforce empty, non-null strings due to the pickiness of the String == String operator +// combined with the semantics of the String(NSString*) constructor +Credential::Credential(const String& user, const String& password, CredentialPersistence persistence) + : m_user(user.length() ? user : "") + , m_password(password.length() ? password : "") + , m_persistence(persistence) +{ +} + +const String& Credential::user() const +{ + return m_user; +} + +const String& Credential::password() const +{ + return m_password; +} + +bool Credential::hasPassword() const +{ + return !m_password.isEmpty(); +} + +CredentialPersistence Credential::persistence() const +{ + return m_persistence; +} + +bool operator==(const Credential& a, const Credential& b) +{ + 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 new file mode 100644 index 0000000..4d80490 --- /dev/null +++ b/WebCore/platform/network/Credential.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 Credential_h +#define Credential_h + +#include "PlatformString.h" + +namespace WebCore { + +enum CredentialPersistence { + CredentialPersistenceNone, + CredentialPersistenceForSession, + CredentialPersistencePermanent +}; + +class Credential { + +public: + Credential(); + Credential(const String& user, const String& password, CredentialPersistence); + + const String& user() const; + const String& password() const; + bool hasPassword() const; + CredentialPersistence persistence() const; + +private: + String m_user; + String m_password; + CredentialPersistence m_persistence; +}; + +bool operator==(const Credential& a, const Credential& b); +inline bool operator!=(const Credential& a, const Credential& b) { return !(a == b); } + +}; +#endif diff --git a/WebCore/platform/network/DNS.h b/WebCore/platform/network/DNS.h new file mode 100644 index 0000000..c232272 --- /dev/null +++ b/WebCore/platform/network/DNS.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2008 Collin Jackson <collinj@webkit.org> + * + * 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 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 COMPUTER, INC. OR + * 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 DNS_h +#define DNS_h + +namespace WebCore { + + class String; + + void prefetchDNS(const String& hostname); +} + +#endif diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp new file mode 100644 index 0000000..0d31856 --- /dev/null +++ b/WebCore/platform/network/FormData.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "FormData.h" + +#include "CString.h" +#include "ChromeClient.h" +#include "FileSystem.h" +#include "TextEncoding.h" + +namespace WebCore { + +inline FormData::FormData() + : m_hasGeneratedFiles(false) + , m_alwaysStream(false) +{ +} + +inline FormData::FormData(const FormData& data) + : RefCounted<FormData>() + , m_elements(data.m_elements) + , m_hasGeneratedFiles(false) + , m_alwaysStream(false) +{ + // We shouldn't be copying FormData that hasn't already removed its generated files + // but just in case, make sure the new FormData is ready to generate its own files. + if (data.m_hasGeneratedFiles) { + size_t n = m_elements.size(); + for (size_t i = 0; i < n; ++i) { + FormDataElement& e = m_elements[i]; + if (e.m_type == FormDataElement::encodedFile) + e.m_generatedFilename = String(); + } + } +} + +FormData::~FormData() +{ + // This cleanup should've happened when the form submission finished. + // Just in case, let's assert, and do the cleanup anyway in release builds. + ASSERT(!m_hasGeneratedFiles); + removeGeneratedFilesIfNeeded(); +} + +PassRefPtr<FormData> FormData::create() +{ + return adoptRef(new FormData); +} + +PassRefPtr<FormData> FormData::create(const void* data, size_t size) +{ + RefPtr<FormData> result = create(); + result->appendData(data, size); + return result.release(); +} + +PassRefPtr<FormData> FormData::create(const CString& string) +{ + RefPtr<FormData> result = create(); + result->appendData(string.data(), string.length()); + return result.release(); +} + +PassRefPtr<FormData> FormData::create(const Vector<char>& vector) +{ + RefPtr<FormData> result = create(); + result->appendData(vector.data(), vector.size()); + return result.release(); +} + +PassRefPtr<FormData> FormData::copy() const +{ + return adoptRef(new FormData(*this)); +} + +void FormData::appendData(const void* data, size_t size) +{ + if (m_elements.isEmpty() || m_elements.last().m_type != FormDataElement::data) + m_elements.append(FormDataElement()); + FormDataElement& e = m_elements.last(); + size_t oldSize = e.m_data.size(); + e.m_data.grow(oldSize + size); + memcpy(e.m_data.data() + oldSize, data, size); +} + +void FormData::appendFile(const String& filename, bool shouldGenerateFile) +{ + m_elements.append(FormDataElement(filename, shouldGenerateFile)); +} + +void FormData::flatten(Vector<char>& data) const +{ + // Concatenate all the byte arrays, but omit any files. + data.clear(); + size_t n = m_elements.size(); + for (size_t i = 0; i < n; ++i) { + const FormDataElement& e = m_elements[i]; + if (e.m_type == FormDataElement::data) { + size_t oldSize = data.size(); + size_t delta = e.m_data.size(); + data.grow(oldSize + delta); + memcpy(data.data() + oldSize, e.m_data.data(), delta); + } + } +} + +String FormData::flattenToString() const +{ + Vector<char> bytes; + flatten(bytes); + return Latin1Encoding().decode(bytes.data(), bytes.size()); +} + +void FormData::generateFiles(ChromeClient* client) +{ + ASSERT(!m_hasGeneratedFiles); + + if (m_hasGeneratedFiles) + return; + + size_t n = m_elements.size(); + for (size_t i = 0; i < n; ++i) { + FormDataElement& e = m_elements[i]; + if (e.m_type == FormDataElement::encodedFile && e.m_shouldGenerateFile) { + e.m_generatedFilename = client->generateReplacementFile(e.m_filename); + m_hasGeneratedFiles = true; + } + } +} + +void FormData::removeGeneratedFilesIfNeeded() +{ + if (!m_hasGeneratedFiles) + return; + + size_t n = m_elements.size(); + for (size_t i = 0; i < n; ++i) { + FormDataElement& e = m_elements[i]; + if (e.m_type == FormDataElement::encodedFile && !e.m_generatedFilename.isEmpty()) { + ASSERT(e.m_shouldGenerateFile); + String directory = directoryName(e.m_generatedFilename); + deleteFile(e.m_generatedFilename); + deleteEmptyDirectory(directory); + e.m_generatedFilename = String(); + } + } + m_hasGeneratedFiles = false; +} + +} // namespace WebCore diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h new file mode 100644 index 0000000..cb91fab --- /dev/null +++ b/WebCore/platform/network/FormData.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef FormData_h +#define FormData_h + +#include "PlatformString.h" +#include <wtf/RefCounted.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class ChromeClient; + +class FormDataElement { +public: + FormDataElement() : m_type(data) { } + FormDataElement(const Vector<char>& array) : m_type(data), m_data(array) { } + FormDataElement(const String& filename, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_shouldGenerateFile(shouldGenerateFile) { } + + enum { data, encodedFile } m_type; + Vector<char> m_data; + String m_filename; + String m_generatedFilename; + bool m_shouldGenerateFile; +}; + +inline bool operator==(const FormDataElement& a, const FormDataElement& b) +{ + if (&a == &b) + return true; + + if (a.m_type != b.m_type) + return false; + if (a.m_data != b.m_data) + return false; + if (a.m_filename != b.m_filename) + return false; + + return true; +} + +inline bool operator!=(const FormDataElement& a, const FormDataElement& b) +{ + return !(a == b); +} + +class FormData : public RefCounted<FormData> { +public: + static PassRefPtr<FormData> create(); + static PassRefPtr<FormData> create(const void*, size_t); + static PassRefPtr<FormData> create(const CString&); + static PassRefPtr<FormData> create(const Vector<char>&); + PassRefPtr<FormData> copy() const; + ~FormData(); + + void appendData(const void* data, size_t); + void appendFile(const String& filename, bool shouldGenerateFile = false); + + void flatten(Vector<char>&) const; // omits files + String flattenToString() const; // omits files + + bool isEmpty() const { return m_elements.isEmpty(); } + const Vector<FormDataElement>& elements() const { return m_elements; } + + void generateFiles(ChromeClient*); + void removeGeneratedFilesIfNeeded(); + + bool alwaysStream() const { return m_alwaysStream; } + void setAlwaysStream(bool alwaysStream) { m_alwaysStream = alwaysStream; } + +private: + FormData(); + FormData(const FormData&); + + Vector<FormDataElement> m_elements; + bool m_hasGeneratedFiles; + bool m_alwaysStream; +}; + +inline bool operator==(const FormData& a, const FormData& b) +{ + return a.elements() == b.elements(); +} + +inline bool operator!=(const FormData& a, const FormData& b) +{ + return a.elements() != b.elements(); +} + +} // namespace WebCore + +#endif diff --git a/WebCore/platform/network/HTTPHeaderMap.h b/WebCore/platform/network/HTTPHeaderMap.h new file mode 100644 index 0000000..dc204cb --- /dev/null +++ b/WebCore/platform/network/HTTPHeaderMap.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 HTTPHeaderMap_h +#define HTTPHeaderMap_h + +#include "StringHash.h" +#include <wtf/HashMap.h> + +namespace WebCore { + + typedef HashMap<String, String, CaseFoldingHash> HTTPHeaderMap; + +} // namespace WebCore + +#endif // HTTPHeaderMap_h diff --git a/WebCore/platform/network/HTTPParsers.cpp b/WebCore/platform/network/HTTPParsers.cpp new file mode 100644 index 0000000..0858fc9 --- /dev/null +++ b/WebCore/platform/network/HTTPParsers.cpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * Copyright (C) 2006, 2007, 2008 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 "HTTPParsers.h" + +#include "PlatformString.h" + +namespace WebCore { + +// true if there is more to parse +static inline bool skipWhiteSpace(const String& str, int& pos, bool fromHttpEquivMeta) +{ + int len = str.length(); + + if (fromHttpEquivMeta) + while (pos != len && str[pos] <= ' ') + ++pos; + else + while (pos != len && (str[pos] == '\t' || str[pos] == ' ')) + ++pos; + + return pos != len; +} + +bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url) +{ + int len = refresh.length(); + int pos = 0; + + if (!skipWhiteSpace(refresh, pos, fromHttpEquivMeta)) + return false; + + while (pos != len && refresh[pos] != ',' && refresh[pos] != ';') + ++pos; + + if (pos == len) { // no URL + url = String(); + bool ok; + delay = refresh.stripWhiteSpace().toDouble(&ok); + return ok; + } else { + bool ok; + delay = refresh.left(pos).stripWhiteSpace().toDouble(&ok); + if (!ok) + return false; + + ++pos; + skipWhiteSpace(refresh, pos, fromHttpEquivMeta); + int urlStartPos = pos; + if (refresh.find("url", urlStartPos, false) == urlStartPos) { + urlStartPos += 3; + skipWhiteSpace(refresh, urlStartPos, fromHttpEquivMeta); + if (refresh[urlStartPos] == '=') { + ++urlStartPos; + skipWhiteSpace(refresh, urlStartPos, fromHttpEquivMeta); + } else + urlStartPos = pos; // e.g. "Refresh: 0; url.html" + } + + int urlEndPos = len; + + if (refresh[urlStartPos] == '"' || refresh[urlStartPos] == '\'') { + UChar quotationMark = refresh[urlStartPos]; + urlStartPos++; + while (urlEndPos > urlStartPos) { + urlEndPos--; + if (refresh[urlEndPos] == quotationMark) + break; + } + } + + url = refresh.substring(urlStartPos, urlEndPos - urlStartPos).stripWhiteSpace(); + return true; + } +} + +String filenameFromHTTPContentDisposition(const String& value) +{ + Vector<String> keyValuePairs; + value.split(';', keyValuePairs); + + unsigned length = keyValuePairs.size(); + for (unsigned i = 0; i < length; i++) { + int valueStartPos = keyValuePairs[i].find('='); + if (valueStartPos < 0) + continue; + + String key = keyValuePairs[i].left(valueStartPos).stripWhiteSpace(); + + if (key.isEmpty() || key != "filename") + continue; + + String value = keyValuePairs[i].substring(valueStartPos + 1).stripWhiteSpace(); + + // Remove quotes if there are any + if (value[0] == '\"') + value = value.substring(1, value.length() - 2); + + return value; + } + + return String(); +} + +String extractMIMETypeFromMediaType(const String& mediaType) +{ + String mimeType; + unsigned length = mediaType.length(); + for (unsigned offset = 0; offset < length; offset++) { + UChar c = mediaType[offset]; + if (c == ';') + break; + else if (isSpaceOrNewline(c)) // FIXME: This seems wrong, " " is an invalid MIME type character according to RFC 2045. bug 8644 + continue; + // FIXME: This is a very slow way to build a string, given WebCore::String's implementation. + mimeType += String(&c, 1); + } + return mimeType; +} + +String extractCharsetFromMediaType(const String& mediaType) +{ + int pos = 0; + int length = (int)mediaType.length(); + + while (pos < length) { + pos = mediaType.find("charset", pos, false); + if (pos <= 0) + return String(); + + // is what we found a beginning of a word? + if (mediaType[pos-1] > ' ' && mediaType[pos-1] != ';') { + pos += 7; + continue; + } + + pos += 7; + + // skip whitespace + while (pos != length && mediaType[pos] <= ' ') + ++pos; + + if (mediaType[pos++] != '=') // this "charset" substring wasn't a parameter name, but there may be others + continue; + + while (pos != length && (mediaType[pos] <= ' ' || mediaType[pos] == '"' || mediaType[pos] == '\'')) + ++pos; + + // we don't handle spaces within quoted parameter values, because charset names cannot have any + int endpos = pos; + while (pos != length && mediaType[endpos] > ' ' && mediaType[endpos] != '"' && mediaType[endpos] != '\'' && mediaType[endpos] != ';') + ++endpos; + + return mediaType.substring(pos, endpos-pos); + } + + return String(); +} +} diff --git a/WebCore/platform/network/HTTPParsers.h b/WebCore/platform/network/HTTPParsers.h new file mode 100644 index 0000000..28a9ce9 --- /dev/null +++ b/WebCore/platform/network/HTTPParsers.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org) + * + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 HTTPParsers_h +#define HTTPParsers_h + +namespace WebCore { + + class String; + + bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& delay, String& url); + String filenameFromHTTPContentDisposition(const String&); + String extractMIMETypeFromMediaType(const String&); + String extractCharsetFromMediaType(const String&); +} + +#endif diff --git a/WebCore/platform/network/NetworkStateNotifier.cpp b/WebCore/platform/network/NetworkStateNotifier.cpp new file mode 100644 index 0000000..d39fc30 --- /dev/null +++ b/WebCore/platform/network/NetworkStateNotifier.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 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. ``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 + * 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 "NetworkStateNotifier.h" + +#include <wtf/Assertions.h> + +namespace WebCore { + +NetworkStateNotifier& networkStateNotifier() +{ + static NetworkStateNotifier networkStateNotifier; + + return networkStateNotifier; +} + +void NetworkStateNotifier::setNetworkStateChangedFunction(void(*function)()) +{ + ASSERT(!m_networkStateChangedFunction); + + m_networkStateChangedFunction = function; +} + +} diff --git a/WebCore/platform/network/NetworkStateNotifier.h b/WebCore/platform/network/NetworkStateNotifier.h new file mode 100644 index 0000000..53ab4c8 --- /dev/null +++ b/WebCore/platform/network/NetworkStateNotifier.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008 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. ``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 + * 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 NetworkStateNotifier_h +#define NetworkStateNotifier_h + +#if PLATFORM(MAC) + +#include <wtf/RetainPtr.h> +#include "Timer.h" + +typedef const struct __CFArray * CFArrayRef; +typedef const struct __SCDynamicStore * SCDynamicStoreRef; + +#elif PLATFORM(CHROMIUM) + +#include "NetworkStateNotifierPrivate.h" + +#elif PLATFORM(WIN) + +#include <windows.h> + +#endif + +namespace WebCore { + +class NetworkStateNotifier { +public: + NetworkStateNotifier(); + void setNetworkStateChangedFunction(void (*)()); + + bool onLine() const { return m_isOnLine; } + +private: + bool m_isOnLine; + void (*m_networkStateChangedFunction)(); + + void updateState(); + +#if PLATFORM(MAC) + void networkStateChangeTimerFired(Timer<NetworkStateNotifier>*); + + static void dynamicStoreCallback(SCDynamicStoreRef, CFArrayRef changedKeys, void *info); + + RetainPtr<SCDynamicStoreRef> m_store; + Timer<NetworkStateNotifier> m_networkStateChangeTimer; + +#elif PLATFORM(WIN) + static void CALLBACK addrChangeCallback(void*, BOOLEAN timedOut); + static void callAddressChanged(void*); + void addressChanged(); + + void registerForAddressChange(); + HANDLE m_waitHandle; + OVERLAPPED m_overlapped; + +#elif PLATFORM(ANDROID) +public: + void networkStateChange(bool online); + +#elif PLATFORM(CHROMIUM) + NetworkStateNotifierPrivate p; +#endif +}; + +#if !PLATFORM(MAC) && !PLATFORM(WIN) && !PLATFORM(CHROMIUM) + +inline NetworkStateNotifier::NetworkStateNotifier() + : m_isOnLine(true) +{ +} + +inline void NetworkStateNotifier::updateState() { } + +#endif + +NetworkStateNotifier& networkStateNotifier(); + +}; + +#endif // NetworkStateNotifier_h diff --git a/WebCore/platform/network/ProtectionSpace.cpp b/WebCore/platform/network/ProtectionSpace.cpp new file mode 100644 index 0000000..bd73558 --- /dev/null +++ b/WebCore/platform/network/ProtectionSpace.cpp @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ProtectionSpace.h" + +#if USE(CFNETWORK) && !PLATFORM(MAC) +#include "AuthenticationCF.h" +#include <CFNetwork/CFURLProtectionSpacePriv.h> +#include <wtf/RetainPtr.h> +#endif + +namespace WebCore { + +// Need to enforce empty, non-null strings due to the pickiness of the String == String operator +// combined with the semantics of the String(NSString*) constructor +ProtectionSpace::ProtectionSpace() + : m_host("") + , m_realm("") +{ +} + +// Need to enforce empty, non-null strings due to the pickiness of the String == String operator +// combined with the semantics of the String(NSString*) constructor +ProtectionSpace::ProtectionSpace(const String& host, int port, ProtectionSpaceServerType serverType, const String& realm, ProtectionSpaceAuthenticationScheme authenticationScheme) + : m_host(host.length() ? host : "") + , m_port(port) + , m_serverType(serverType) + , m_realm(realm.length() ? realm : "") + , m_authenticationScheme(authenticationScheme) +{ +} + +const String& ProtectionSpace::host() const +{ + return m_host; +} + +int ProtectionSpace::port() const +{ + return m_port; +} + +ProtectionSpaceServerType ProtectionSpace::serverType() const +{ + return m_serverType; +} + +bool ProtectionSpace::isProxy() const +{ + return (m_serverType == ProtectionSpaceProxyHTTP || + m_serverType == ProtectionSpaceProxyHTTPS || + m_serverType == ProtectionSpaceProxyFTP || + m_serverType == ProtectionSpaceProxySOCKS); +} + +const String& ProtectionSpace::realm() const +{ + return m_realm; +} + +ProtectionSpaceAuthenticationScheme ProtectionSpace::authenticationScheme() const +{ + return m_authenticationScheme; +} + +bool ProtectionSpace::receivesCredentialSecurely() const +{ +#if USE(CFNETWORK) && !PLATFORM(MAC) + RetainPtr<CFURLProtectionSpaceRef> cfSpace(AdoptCF, createCF(*this)); + return cfSpace && CFURLProtectionSpaceReceivesCredentialSecurely(cfSpace.get()); +#else + return (m_serverType == ProtectionSpaceServerHTTPS || + m_serverType == ProtectionSpaceServerFTPS || + m_serverType == ProtectionSpaceProxyHTTPS || + m_authenticationScheme == ProtectionSpaceAuthenticationSchemeHTTPDigest); +#endif +} + +bool operator==(const ProtectionSpace& a, const ProtectionSpace& b) +{ + if (a.host() != b.host()) + return false; + if (a.port() != b.port()) + return false; + if (a.serverType() != b.serverType()) + return false; + if (a.realm() != b.realm()) + return false; + if (a.authenticationScheme() != b.authenticationScheme()) + return false; + + return true; +} + +} + + diff --git a/WebCore/platform/network/ProtectionSpace.h b/WebCore/platform/network/ProtectionSpace.h new file mode 100644 index 0000000..9a73cff --- /dev/null +++ b/WebCore/platform/network/ProtectionSpace.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ProtectionSpace_h +#define ProtectionSpace_h + +#include "PlatformString.h" + +namespace WebCore { + +enum ProtectionSpaceServerType { + ProtectionSpaceServerHTTP = 1, + ProtectionSpaceServerHTTPS = 2, + ProtectionSpaceServerFTP = 3, + ProtectionSpaceServerFTPS = 4, + ProtectionSpaceProxyHTTP = 5, + ProtectionSpaceProxyHTTPS = 6, + ProtectionSpaceProxyFTP = 7, + ProtectionSpaceProxySOCKS = 8 +}; + +enum ProtectionSpaceAuthenticationScheme { + ProtectionSpaceAuthenticationSchemeDefault = 1, + ProtectionSpaceAuthenticationSchemeHTTPBasic = 2, + ProtectionSpaceAuthenticationSchemeHTTPDigest = 3, + ProtectionSpaceAuthenticationSchemeHTMLForm = 4, + ProtectionSpaceAuthenticationSchemeNTLM = 5, + ProtectionSpaceAuthenticationSchemeNegotiate = 6, +}; + +class ProtectionSpace { + +public: + ProtectionSpace(); + ProtectionSpace(const String& host, int port, ProtectionSpaceServerType, const String& realm, ProtectionSpaceAuthenticationScheme); + + const String& host() const; + int port() const; + ProtectionSpaceServerType serverType() const; + bool isProxy() const; + const String& realm() const; + ProtectionSpaceAuthenticationScheme authenticationScheme() const; + + bool receivesCredentialSecurely() const; + +private: + String m_host; + int m_port; + ProtectionSpaceServerType m_serverType; + String m_realm; + ProtectionSpaceAuthenticationScheme m_authenticationScheme; +}; + +bool operator==(const ProtectionSpace& a, const ProtectionSpace& b); +inline bool operator!=(const ProtectionSpace& a, const ProtectionSpace& b) { return !(a == b); } + +} +#endif diff --git a/WebCore/platform/network/ResourceErrorBase.cpp b/WebCore/platform/network/ResourceErrorBase.cpp new file mode 100644 index 0000000..1ea35b0 --- /dev/null +++ b/WebCore/platform/network/ResourceErrorBase.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceError.h" + +namespace WebCore { + +void ResourceErrorBase::lazyInit() const +{ + const_cast<ResourceError*>(static_cast<const ResourceError*>(this))->platformLazyInit(); +} + +bool ResourceErrorBase::compare(const ResourceError& a, const ResourceError& b) +{ + if (a.isNull() && b.isNull()) + return true; + + if (a.isNull() || b.isNull()) + return false; + + if (a.domain() != b.domain()) + return false; + + if (a.errorCode() != b.errorCode()) + return false; + + if (a.failingURL() != b.failingURL()) + return false; + + if (a.localizedDescription() != b.localizedDescription()) + return false; + + if (a.isCancellation() != b.isCancellation()) + return false; + + return platformCompare(a, b); +} + +} diff --git a/WebCore/platform/network/ResourceErrorBase.h b/WebCore/platform/network/ResourceErrorBase.h new file mode 100644 index 0000000..b2aac67 --- /dev/null +++ b/WebCore/platform/network/ResourceErrorBase.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceErrorBase_h +#define ResourceErrorBase_h + +#include "PlatformString.h" + +namespace WebCore { + +class ResourceError; + +class ResourceErrorBase { +public: + bool isNull() const { return m_isNull; } + + const String& domain() const { lazyInit(); return m_domain; } + int errorCode() const { lazyInit(); return m_errorCode; } + const String& failingURL() const { lazyInit(); return m_failingURL; } + const String& localizedDescription() const { lazyInit(); return m_localizedDescription; } + + void setIsCancellation(bool isCancellation) { m_isCancellation = isCancellation; } + bool isCancellation() const { return m_isCancellation; } + + static bool compare(const ResourceError& a, const ResourceError& b); + +protected: + ResourceErrorBase() + : m_errorCode(0) + , m_isNull(true) + , m_isCancellation(false) + { + } + + ResourceErrorBase(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : m_domain(domain) + , m_errorCode(errorCode) + , m_failingURL(failingURL) + , m_localizedDescription(localizedDescription) + , m_isNull(false) + , m_isCancellation(false) + { + } + + void lazyInit() const; + + // The ResourceError subclass may "shadow" this method to lazily initialize platform specific fields + void platformLazyInit() {} + + // The ResourceError subclass may "shadow" this method to compare platform specific fields + static bool platformCompare(const ResourceError& a, const ResourceError& b) { return true; } + + String m_domain; + int m_errorCode; + String m_failingURL; + String m_localizedDescription; + bool m_isNull; + bool m_isCancellation; +}; + +inline bool operator==(const ResourceError& a, const ResourceError& b) { return ResourceErrorBase::compare(a, b); } +inline bool operator!=(const ResourceError& a, const ResourceError& b) { return !(a == b); } + +} // namespace WebCore + +#endif // ResourceErrorBase_h_ diff --git a/WebCore/platform/network/ResourceHandle.cpp b/WebCore/platform/network/ResourceHandle.cpp new file mode 100644 index 0000000..149411e --- /dev/null +++ b/WebCore/platform/network/ResourceHandle.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2004, 2006, 2007, 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceHandle.h" +#include "ResourceHandleInternal.h" + +#include "Logging.h" +#include "ResourceHandleClient.h" +#include "Timer.h" +#include <algorithm> + +namespace WebCore { + +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)) +{ +} + +PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, ResourceHandleClient* client, + Frame* frame, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle) +{ + RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle))); + + if (!request.url().isValid()) { + newHandle->scheduleFailure(InvalidURLFailure); + return newHandle.release(); + } + + if (!portAllowed(request)) { + newHandle->scheduleFailure(BlockedFailure); + return newHandle.release(); + } + + if (newHandle->start(frame)) + return newHandle.release(); + + return 0; +} + +void ResourceHandle::scheduleFailure(FailureType type) +{ + d->m_failureType = type; + d->m_failureTimer.startOneShot(0); +} + +void ResourceHandle::fireFailure(Timer<ResourceHandle>*) +{ + if (!client()) + return; + + switch (d->m_failureType) { + case BlockedFailure: + client()->wasBlocked(this); + return; + case InvalidURLFailure: + client()->cannotShowURL(this); + return; + } + + ASSERT_NOT_REACHED(); +} + +ResourceHandleClient* ResourceHandle::client() const +{ + return d->m_client; +} + +void ResourceHandle::setClient(ResourceHandleClient* client) +{ + d->m_client = client; +} + +const ResourceRequest& ResourceHandle::request() const +{ + return d->m_request; +} + +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 + 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; +} + +} // namespace WebCore diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h new file mode 100644 index 0000000..304bdbe --- /dev/null +++ b/WebCore/platform/network/ResourceHandle.h @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceHandle_h +#define ResourceHandle_h + +#include "AuthenticationChallenge.h" +#include "HTTPHeaderMap.h" +#include <wtf/OwnPtr.h> + +#if PLATFORM(CF) +typedef const struct __CFData * CFDataRef; +#endif + +#if PLATFORM(WIN) +typedef unsigned long DWORD; +typedef unsigned long DWORD_PTR; +typedef void* LPVOID; +typedef LPVOID HINTERNET; +typedef unsigned WPARAM; +typedef long LPARAM; +typedef struct HWND__* HWND; +typedef _W64 long LONG_PTR; +typedef LONG_PTR LRESULT; +#endif + + +#if PLATFORM(MAC) +#include <wtf/RetainPtr.h> +#ifdef __OBJC__ +@class NSData; +@class NSError; +@class NSURLConnection; +@class WebCoreResourceHandleAsDelegate; +#else +class NSData; +class NSError; +class NSURLConnection; +class WebCoreResourceHandleAsDelegate; +typedef struct objc_object *id; +#endif +#endif + +#if USE(CFNETWORK) +typedef struct _CFURLConnection* CFURLConnectionRef; +typedef int CFHTTPCookieStorageAcceptPolicy; +typedef struct OpaqueCFHTTPCookieStorage* CFHTTPCookieStorageRef; +#endif + +namespace WebCore { + +class AuthenticationChallenge; +class Credential; +class FormData; +class Frame; +class KURL; +class ResourceError; +class ResourceHandleClient; +class ResourceHandleInternal; +class ResourceRequest; +class ResourceResponse; +class SchedulePair; +class SharedBuffer; +class SubresourceLoader; +class SubresourceLoaderClient; + +template <typename T> class Timer; + +class ResourceHandle : public RefCounted<ResourceHandle> { +private: + ResourceHandle(const ResourceRequest&, ResourceHandleClient*, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle); + + enum FailureType { + BlockedFailure, + InvalidURLFailure + }; + +public: + // FIXME: should not need the Frame + static PassRefPtr<ResourceHandle> create(const ResourceRequest&, ResourceHandleClient*, Frame*, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle = false); + + static void loadResourceSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data, Frame* frame); + static bool willLoadFromCache(ResourceRequest&); +#if PLATFORM(MAC) + static bool didSendBodyDataDelegateExists(); +#endif + + ~ResourceHandle(); + +#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&); +#endif + +#if PLATFORM(MAC) + void didCancelAuthenticationChallenge(const AuthenticationChallenge&); + NSURLConnection *connection() const; + WebCoreResourceHandleAsDelegate *delegate(); + void releaseDelegate(); + id releaseProxy(); + + void schedule(SchedulePair*); + void unschedule(SchedulePair*); +#elif USE(CFNETWORK) + static CFRunLoopRef loaderRunLoop(); + CFURLConnectionRef connection() const; + CFURLConnectionRef releaseConnectionForDownload(); + static void setHostAllowsAnyHTTPSCertificate(const String&); + static void setClientCertificate(const String& host, CFDataRef); +#endif + +#if PLATFORM(WIN) && USE(CURL) + static void setHostAllowsAnyHTTPSCertificate(const String&); +#endif +#if PLATFORM(WIN) && USE(CURL) && PLATFORM(CF) + static void setClientCertificate(const String& host, CFDataRef); +#endif + + PassRefPtr<SharedBuffer> bufferedData(); + static bool supportsBufferedData(); + +#if USE(WININET) + void setHasReceivedResponse(bool = true); + bool hasReceivedResponse() const; + void fileLoadTimer(Timer<ResourceHandle>*); + void onHandleCreated(LPARAM); + void onRequestRedirected(LPARAM); + void onRequestComplete(LPARAM); + friend void __stdcall transferJobStatusCallback(HINTERNET, DWORD_PTR, DWORD, LPVOID, DWORD); + friend LRESULT __stdcall ResourceHandleWndProc(HWND, unsigned message, WPARAM, LPARAM); +#endif + +#if PLATFORM(QT) || USE(CURL) || USE(SOUP) || defined(ANDROID) + ResourceHandleInternal* getInternal() { return d.get(); } +#endif + + // Used to work around the fact that you don't get any more NSURLConnection callbacks until you return from the one you're in. + static bool loadsBlocked(); + + void clearAuthentication(); + void cancel(); + + // The client may be 0, in which case no callbacks will be made. + ResourceHandleClient* client() const; + void setClient(ResourceHandleClient*); + + void setDefersLoading(bool); + + const ResourceRequest& request() const; + + void fireFailure(Timer<ResourceHandle>*); + +private: +#if USE(SOUP) + bool startData(String urlString); + bool startHttp(String urlString); + bool startGio(String urlString); +#endif + + void scheduleFailure(FailureType); + + bool start(Frame*); + + friend class ResourceHandleInternal; + OwnPtr<ResourceHandleInternal> d; +}; + +} + +#endif // ResourceHandle_h diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h new file mode 100644 index 0000000..08e06a2 --- /dev/null +++ b/WebCore/platform/network/ResourceHandleClient.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceHandleClient_h +#define ResourceHandleClient_h + +#include <wtf/RefCounted.h> +#include <wtf/Platform.h> +#include <wtf/RefPtr.h> + +#if USE(CFNETWORK) +#include <ConditionalMacros.h> +#include <CFNetwork/CFURLResponsePriv.h> +#endif + +#if PLATFORM(MAC) +#ifdef __OBJC__ +@class NSCachedURLResponse; +#else +class NSCachedURLResponse; +#endif +#endif + +namespace WebCore { + class AuthenticationChallenge; + class Credential; + class KURL; + class ResourceHandle; + class ResourceError; + class ResourceRequest; + class ResourceResponse; + + enum CacheStoragePolicy { + StorageAllowed, + StorageAllowedInMemoryOnly, + StorageNotAllowed, + }; + + class ResourceHandleClient { + public: + virtual ~ResourceHandleClient() { } + + // request may be modified + virtual void willSendRequest(ResourceHandle*, ResourceRequest&, const ResourceResponse& redirectResponse) { } + virtual void didSendData(ResourceHandle*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) { } + + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&) { } + virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived) { } + virtual void didFinishLoading(ResourceHandle*) { } + virtual void didFail(ResourceHandle*, const ResourceError&) { } + virtual void wasBlocked(ResourceHandle*) { } + virtual void cannotShowURL(ResourceHandle*) { } + + virtual void willCacheResponse(ResourceHandle*, CacheStoragePolicy&) { } + + virtual void didReceiveAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { } + virtual void didCancelAuthenticationChallenge(ResourceHandle*, const AuthenticationChallenge&) { } + virtual void receivedCredential(ResourceHandle*, const AuthenticationChallenge&, const Credential&) { } + virtual void receivedRequestToContinueWithoutCredential(ResourceHandle*, const AuthenticationChallenge&) { } + virtual void receivedCancellation(ResourceHandle*, const AuthenticationChallenge&) { } + +#if PLATFORM(MAC) + virtual NSCachedURLResponse* willCacheResponse(ResourceHandle*, NSCachedURLResponse* response) { return response; } + virtual void willStopBufferingData(ResourceHandle*, const char*, int) { } +#endif + }; + +} + +#endif diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h new file mode 100644 index 0000000..0bfa9da --- /dev/null +++ b/WebCore/platform/network/ResourceHandleInternal.h @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceHandleInternal_h +#define ResourceHandleInternal_h + +#include "ResourceHandle.h" +#include "ResourceRequest.h" +#include "AuthenticationChallenge.h" +#include "Timer.h" + +#if USE(CFNETWORK) +#include <CFNetwork/CFURLConnectionPriv.h> +#endif + +#if USE(WININET) +#include <winsock2.h> +#include <windows.h> +#endif + +#if USE(CURL) +#include <curl/curl.h> +#include "FormDataStreamCurl.h" +#endif + +#if USE(SOUP) +#include <libsoup/soup.h> +#endif + +#if PLATFORM(QT) +class QWebFrame; +class QWebNetworkJob; +namespace WebCore { +class QNetworkReplyHandler; +} +#endif + +#if PLATFORM(MAC) +#ifdef __OBJC__ +@class NSURLAuthenticationChallenge; +@class NSURLConnection; +#else +class NSURLAuthenticationChallenge; +class NSURLConnection; +#endif +#endif + +#if PLATFORM(ANDROID) +namespace android { + class WebCoreResourceLoader; +} +#endif + +// The allocations and releases in ResourceHandleInternal are +// Cocoa-exception-free (either simple Foundation classes or +// WebCoreResourceLoaderImp which avoids doing work in dealloc). + +namespace WebCore { + class ResourceHandleClient; + + class ResourceHandleInternal : Noncopyable { + public: + ResourceHandleInternal(ResourceHandle* loader, const ResourceRequest& request, ResourceHandleClient* c, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle) + : m_client(c) + , m_request(request) + , status(0) + , m_defersLoading(defersLoading) + , m_shouldContentSniff(shouldContentSniff) + , m_mightDownloadFromHandle(mightDownloadFromHandle) +#if USE(CFNETWORK) + , m_connection(0) +#endif +#if USE(WININET) + , m_fileHandle(INVALID_HANDLE_VALUE) + , m_fileLoadTimer(loader, &ResourceHandle::fileLoadTimer) + , m_resourceHandle(0) + , m_secondaryHandle(0) + , m_jobId(0) + , m_threadId(0) + , m_writing(false) + , m_formDataString(0) + , m_formDataLength(0) + , m_bytesRemainingToWrite(0) + , m_hasReceivedResponse(false) + , m_resend(false) +#endif +#if USE(CURL) + , m_handle(0) + , m_url(0) + , m_customHeaders(0) + , m_cancelled(false) + , m_formDataStream(loader) +#endif +#if USE(SOUP) + , m_msg(0) + , m_cancelled(false) + , m_gfile(0) + , m_input_stream(0) + , m_cancellable(0) + , m_buffer(0) + , m_bufsize(0) + , m_total(0) +#endif +#if PLATFORM(QT) + , m_job(0) + , m_frame(0) +#endif +#if PLATFORM(MAC) + , m_startWhenScheduled(false) + , m_currentMacChallenge(nil) +#elif USE(CFNETWORK) + , m_currentCFChallenge(0) +#endif +#if PLATFORM(ANDROID) + , m_loader(0) +#endif + , m_failureTimer(loader, &ResourceHandle::fireFailure) + { + } + + ~ResourceHandleInternal(); + + ResourceHandleClient* client() { return m_client; } + ResourceHandleClient* m_client; + + ResourceRequest m_request; + + int status; + + bool m_defersLoading; + bool m_shouldContentSniff; + bool m_mightDownloadFromHandle; +#if USE(CFNETWORK) + RetainPtr<CFURLConnectionRef> m_connection; +#elif PLATFORM(MAC) + RetainPtr<NSURLConnection> m_connection; + RetainPtr<WebCoreResourceHandleAsDelegate> m_delegate; + RetainPtr<id> m_proxy; + bool m_startWhenScheduled; +#endif +#if USE(WININET) + HANDLE m_fileHandle; + Timer<ResourceHandle> m_fileLoadTimer; + HINTERNET m_resourceHandle; + HINTERNET m_secondaryHandle; + unsigned m_jobId; + DWORD m_threadId; + bool m_writing; + char* m_formDataString; + int m_formDataLength; + int m_bytesRemainingToWrite; + String m_postReferrer; + bool m_hasReceivedResponse; + bool m_resend; +#endif +#if USE(CURL) + CURL* m_handle; + char* m_url; + struct curl_slist* m_customHeaders; + ResourceResponse m_response; + bool m_cancelled; + + FormDataStream m_formDataStream; + Vector<char> m_postBytes; +#endif +#if USE(SOUP) + SoupMessage* m_msg; + ResourceResponse m_response; + bool m_cancelled; + GFile* m_gfile; + GInputStream* m_input_stream; + GCancellable* m_cancellable; + char* m_buffer; + gsize m_bufsize, m_total; +#endif +#if PLATFORM(QT) +#if QT_VERSION < 0x040400 + QWebNetworkJob* m_job; +#else + QNetworkReplyHandler* m_job; +#endif + QWebFrame* m_frame; +#endif +#if PLATFORM(MAC) + NSURLAuthenticationChallenge *m_currentMacChallenge; +#endif +#if USE(CFNETWORK) + CFURLAuthChallengeRef m_currentCFChallenge; +#endif +#if PLATFORM(ANDROID) + android::WebCoreResourceLoader* m_loader; +#endif + AuthenticationChallenge m_currentWebChallenge; + + ResourceHandle::FailureType m_failureType; + Timer<ResourceHandle> m_failureTimer; + }; + +} // namespace WebCore + +#endif // ResourceHandleInternal_h diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp new file mode 100644 index 0000000..4784bbe --- /dev/null +++ b/WebCore/platform/network/ResourceRequestBase.cpp @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceRequestBase.h" +#include "ResourceRequest.h" + +namespace WebCore { + +inline const ResourceRequest& ResourceRequestBase::asResourceRequest() const +{ + return *static_cast<const ResourceRequest*>(this); +} + +bool ResourceRequestBase::isEmpty() const +{ + updateResourceRequest(); + + return m_url.isEmpty(); +} + +bool ResourceRequestBase::isNull() const +{ + updateResourceRequest(); + + return m_url.isNull(); +} + +const KURL& ResourceRequestBase::url() const +{ + updateResourceRequest(); + + return m_url; +} + +void ResourceRequestBase::setURL(const KURL& url) +{ + updateResourceRequest(); + + m_url = url; + + m_platformRequestUpdated = false; +} + +ResourceRequestCachePolicy ResourceRequestBase::cachePolicy() const +{ + updateResourceRequest(); + + return m_cachePolicy; +} + +void ResourceRequestBase::setCachePolicy(ResourceRequestCachePolicy cachePolicy) +{ + updateResourceRequest(); + + m_cachePolicy = cachePolicy; + + m_platformRequestUpdated = false; +} + +double ResourceRequestBase::timeoutInterval() const +{ + updateResourceRequest(); + + return m_timeoutInterval; +} + +void ResourceRequestBase::setTimeoutInterval(double timeoutInterval) +{ + updateResourceRequest(); + + m_timeoutInterval = timeoutInterval; + + m_platformRequestUpdated = false; +} + +const KURL& ResourceRequestBase::mainDocumentURL() const +{ + updateResourceRequest(); + + return m_mainDocumentURL; +} + +void ResourceRequestBase::setMainDocumentURL(const KURL& mainDocumentURL) +{ + updateResourceRequest(); + + m_mainDocumentURL = mainDocumentURL; + + m_platformRequestUpdated = false; +} + +const String& ResourceRequestBase::httpMethod() const +{ + updateResourceRequest(); + + return m_httpMethod; +} + +void ResourceRequestBase::setHTTPMethod(const String& httpMethod) +{ + updateResourceRequest(); + + m_httpMethod = httpMethod; + + m_platformRequestUpdated = false; +} + +const HTTPHeaderMap& ResourceRequestBase::httpHeaderFields() const +{ + updateResourceRequest(); + + return m_httpHeaderFields; +} + +String ResourceRequestBase::httpHeaderField(const String& name) const +{ + updateResourceRequest(); + + return m_httpHeaderFields.get(name); +} + +void ResourceRequestBase::setHTTPHeaderField(const String& name, const String& value) +{ + updateResourceRequest(); + + m_httpHeaderFields.set(name, value); + + m_platformRequestUpdated = false; +} + +FormData* ResourceRequestBase::httpBody() const +{ + updateResourceRequest(); + + return m_httpBody.get(); +} + +void ResourceRequestBase::setHTTPBody(PassRefPtr<FormData> httpBody) +{ + updateResourceRequest(); + + m_httpBody = httpBody; + + m_platformRequestUpdated = false; +} + +bool ResourceRequestBase::allowHTTPCookies() const +{ + updateResourceRequest(); + + return m_allowHTTPCookies; +} + +void ResourceRequestBase::setAllowHTTPCookies(bool allowHTTPCookies) +{ + updateResourceRequest(); + + m_allowHTTPCookies = allowHTTPCookies; + + m_platformRequestUpdated = false; +} + +void ResourceRequestBase::addHTTPHeaderField(const String& name, const String& value) +{ + updateResourceRequest(); + pair<HTTPHeaderMap::iterator, bool> result = m_httpHeaderFields.add(name, value); + if (!result.second) + result.first->second += "," + value; +} + +void ResourceRequestBase::addHTTPHeaderFields(const HTTPHeaderMap& headerFields) +{ + HTTPHeaderMap::const_iterator end = headerFields.end(); + for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it) + addHTTPHeaderField(it->first, it->second); +} + +bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceRequestBase& b) +{ + if (a.url() != b.url()) + return false; + + if (a.cachePolicy() != b.cachePolicy()) + return false; + + if (a.timeoutInterval() != b.timeoutInterval()) + return false; + + if (a.mainDocumentURL() != b.mainDocumentURL()) + return false; + + if (a.httpMethod() != b.httpMethod()) + return false; + + if (a.allowHTTPCookies() != b.allowHTTPCookies()) + return false; + + FormData* formDataA = a.httpBody(); + FormData* formDataB = b.httpBody(); + + if (!formDataA) + return !formDataB; + if (!formDataB) + return !formDataA; + + if (*formDataA != *formDataB) + return false; + + return true; +} + +bool operator==(const ResourceRequestBase& a, const ResourceRequestBase& b) +{ + if (!equalIgnoringHeaderFields(a, b)) + return false; + + if (a.httpHeaderFields() != b.httpHeaderFields()) + return false; + + return true; +} + +bool ResourceRequestBase::isConditional() const +{ + return (m_httpHeaderFields.contains("If-Match") || + m_httpHeaderFields.contains("If-Modified-Since") || + m_httpHeaderFields.contains("If-None-Match") || + m_httpHeaderFields.contains("If-Range") || + m_httpHeaderFields.contains("If-Unmodified-Since")); +} + +void ResourceRequestBase::updatePlatformRequest() const +{ + if (m_platformRequestUpdated) + return; + + const_cast<ResourceRequest&>(asResourceRequest()).doUpdatePlatformRequest(); + m_platformRequestUpdated = true; +} + +void ResourceRequestBase::updateResourceRequest() const +{ + if (m_resourceRequestUpdated) + return; + + const_cast<ResourceRequest&>(asResourceRequest()).doUpdateResourceRequest(); + m_resourceRequestUpdated = true; +} + +} diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h new file mode 100644 index 0000000..32a3384 --- /dev/null +++ b/WebCore/platform/network/ResourceRequestBase.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequestBase_h +#define ResourceRequestBase_h + +#include "FormData.h" +#include "KURL.h" +#include "HTTPHeaderMap.h" + +namespace WebCore { + + enum ResourceRequestCachePolicy { + UseProtocolCachePolicy, // normal load + ReloadIgnoringCacheData, // reload + ReturnCacheDataElseLoad, // back/forward or encoding change - allow stale data + ReturnCacheDataDontLoad, // results of a post - allow stale data and only use cache + }; + + const int unspecifiedTimeoutInterval = INT_MAX; + + class ResourceRequest; + + // Do not use this type directly. Use ResourceRequest instead. + class ResourceRequestBase { + public: + bool isNull() const; + bool isEmpty() const; + + const KURL& url() const; + void setURL(const KURL& url); + + ResourceRequestCachePolicy cachePolicy() const; + void setCachePolicy(ResourceRequestCachePolicy cachePolicy); + + double timeoutInterval() const; + void setTimeoutInterval(double timeoutInterval); + + const KURL& mainDocumentURL() const; + void setMainDocumentURL(const KURL& mainDocumentURL); + + const String& httpMethod() const; + void setHTTPMethod(const String& httpMethod); + + const HTTPHeaderMap& httpHeaderFields() const; + String httpHeaderField(const String& name) const; + void setHTTPHeaderField(const String& name, const String& value); + void addHTTPHeaderField(const String& name, const String& value); + void addHTTPHeaderFields(const HTTPHeaderMap& headerFields); + + String httpContentType() const { return httpHeaderField("Content-Type"); } + void setHTTPContentType(const String& httpContentType) { setHTTPHeaderField("Content-Type", httpContentType); } + + String httpReferrer() const { return httpHeaderField("Referer"); } + void setHTTPReferrer(const String& httpReferrer) { setHTTPHeaderField("Referer", httpReferrer); } + void clearHTTPReferrer() { m_httpHeaderFields.remove("Referer"); } + + String httpOrigin() const { return httpHeaderField("Origin"); } + void setHTTPOrigin(const String& httpOrigin) { setHTTPHeaderField("Origin", httpOrigin); } + void clearHTTPOrigin() { m_httpHeaderFields.remove("Origin"); } + + String httpUserAgent() const { return httpHeaderField("User-Agent"); } + void setHTTPUserAgent(const String& httpUserAgent) { setHTTPHeaderField("User-Agent", httpUserAgent); } + + String httpAccept() const { return httpHeaderField("Accept"); } + void setHTTPAccept(const String& httpAccept) { setHTTPHeaderField("Accept", httpAccept); } + + FormData* httpBody() const; + void setHTTPBody(PassRefPtr<FormData> httpBody); + + bool allowHTTPCookies() const; + void setAllowHTTPCookies(bool allowHTTPCookies); + + bool isConditional() const; + + protected: + // Used when ResourceRequest is initialized from a platform representation of the request + ResourceRequestBase() + : m_resourceRequestUpdated(false) + , m_platformRequestUpdated(true) + { + } + + ResourceRequestBase(const KURL& url, ResourceRequestCachePolicy policy) + : m_url(url) + , m_cachePolicy(policy) + , m_timeoutInterval(unspecifiedTimeoutInterval) + , m_httpMethod("GET") + , m_allowHTTPCookies(true) + , m_resourceRequestUpdated(true) + , m_platformRequestUpdated(false) + { + } + + void updatePlatformRequest() const; + void updateResourceRequest() const; + + KURL m_url; + + ResourceRequestCachePolicy m_cachePolicy; + double m_timeoutInterval; + KURL m_mainDocumentURL; + String m_httpMethod; + HTTPHeaderMap m_httpHeaderFields; + RefPtr<FormData> m_httpBody; + bool m_allowHTTPCookies; + mutable bool m_resourceRequestUpdated; + mutable bool m_platformRequestUpdated; + + private: + const ResourceRequest& asResourceRequest() const; + }; + + bool equalIgnoringHeaderFields(const ResourceRequestBase&, const ResourceRequestBase&); + + bool operator==(const ResourceRequestBase&, const ResourceRequestBase&); + inline bool operator!=(ResourceRequestBase& a, const ResourceRequestBase& b) { return !(a == b); } + +} // namespace WebCore + +#endif // ResourceRequestBase_h diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp new file mode 100644 index 0000000..a9ddc30 --- /dev/null +++ b/WebCore/platform/network/ResourceResponseBase.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceResponseBase.h" +#include "ResourceResponse.h" + +namespace WebCore { + +bool ResourceResponseBase::isHTTP() const +{ + lazyInit(); + + String protocol = m_url.protocol(); + + return equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https"); +} + +const KURL& ResourceResponseBase::url() const +{ + lazyInit(); + + return m_url; +} + +void ResourceResponseBase::setUrl(const KURL& url) +{ + lazyInit(); + m_isNull = false; + + m_url = url; +} + +const String& ResourceResponseBase::mimeType() const +{ + lazyInit(); + + return m_mimeType; +} + +void ResourceResponseBase::setMimeType(const String& mimeType) +{ + lazyInit(); + m_isNull = false; + + m_mimeType = mimeType; +} + +long long ResourceResponseBase::expectedContentLength() const +{ + lazyInit(); + + return m_expectedContentLength; +} + +void ResourceResponseBase::setExpectedContentLength(long long expectedContentLength) +{ + lazyInit(); + m_isNull = false; + + m_expectedContentLength = expectedContentLength; +} + +const String& ResourceResponseBase::textEncodingName() const +{ + lazyInit(); + + return m_textEncodingName; +} + +void ResourceResponseBase::setTextEncodingName(const String& encodingName) +{ + lazyInit(); + m_isNull = false; + + m_textEncodingName = encodingName; +} + +// FIXME should compute this on the fly +const String& ResourceResponseBase::suggestedFilename() const +{ + lazyInit(); + + return m_suggestedFilename; +} + +void ResourceResponseBase::setSuggestedFilename(const String& suggestedName) +{ + lazyInit(); + m_isNull = false; + + m_suggestedFilename = suggestedName; +} + +int ResourceResponseBase::httpStatusCode() const +{ + lazyInit(); + + return m_httpStatusCode; +} + +void ResourceResponseBase::setHTTPStatusCode(int statusCode) +{ + lazyInit(); + + m_httpStatusCode = statusCode; +} + +const String& ResourceResponseBase::httpStatusText() const +{ + lazyInit(); + + return m_httpStatusText; +} + +void ResourceResponseBase::setHTTPStatusText(const String& statusText) +{ + lazyInit(); + + m_httpStatusText = statusText; +} + +String ResourceResponseBase::httpHeaderField(const String& name) const +{ + lazyInit(); + + return m_httpHeaderFields.get(name); +} + +void ResourceResponseBase::setHTTPHeaderField(const String& name, const String& value) +{ + lazyInit(); + + m_httpHeaderFields.set(name, value); +} + +const HTTPHeaderMap& ResourceResponseBase::httpHeaderFields() const +{ + lazyInit(); + + return m_httpHeaderFields; +} + +bool ResourceResponseBase::isAttachment() const +{ + lazyInit(); + + String value = m_httpHeaderFields.get("Content-Disposition"); + int loc = value.find(';'); + if (loc != -1) + value = value.left(loc); + value = value.stripWhiteSpace(); + return equalIgnoringCase(value, "attachment"); +} + +void ResourceResponseBase::setExpirationDate(time_t expirationDate) +{ + lazyInit(); + + m_expirationDate = expirationDate; +} + +time_t ResourceResponseBase::expirationDate() const +{ + lazyInit(); + + return m_expirationDate; +} + +void ResourceResponseBase::setLastModifiedDate(time_t lastModifiedDate) +{ + lazyInit(); + + m_lastModifiedDate = lastModifiedDate; +} + +time_t ResourceResponseBase::lastModifiedDate() const +{ + lazyInit(); + + return m_lastModifiedDate; +} + +void ResourceResponseBase::lazyInit() const +{ + const_cast<ResourceResponse*>(static_cast<const ResourceResponse*>(this))->platformLazyInit(); +} + +bool ResourceResponseBase::compare(const ResourceResponse& a, const ResourceResponse& b) +{ + if (a.isNull() != b.isNull()) + return false; + if (a.url() != b.url()) + return false; + if (a.mimeType() != b.mimeType()) + return false; + if (a.expectedContentLength() != b.expectedContentLength()) + return false; + if (a.textEncodingName() != b.textEncodingName()) + return false; + if (a.suggestedFilename() != b.suggestedFilename()) + return false; + if (a.httpStatusCode() != b.httpStatusCode()) + return false; + if (a.httpStatusText() != b.httpStatusText()) + return false; + if (a.httpHeaderFields() != b.httpHeaderFields()) + return false; + if (a.expirationDate() != b.expirationDate()) + return false; + return ResourceResponse::platformCompare(a, b); +} + +} diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h new file mode 100644 index 0000000..06b0499 --- /dev/null +++ b/WebCore/platform/network/ResourceResponseBase.h @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponseBase_h +#define ResourceResponseBase_h + +#include "HTTPHeaderMap.h" +#include "KURL.h" + +namespace WebCore { + +class ResourceResponse; + +// Do not use this class directly, use the class ResponseResponse instead +class ResourceResponseBase { + public: + + bool isNull() const { return m_isNull; } + bool isHTTP() const; + + const KURL& url() const; + void setUrl(const KURL& url); + + const String& mimeType() const; + void setMimeType(const String& mimeType); + + long long expectedContentLength() const; + void setExpectedContentLength(long long expectedContentLength); + + const String& textEncodingName() const; + void setTextEncodingName(const String& name); + + // FIXME should compute this on the fly + const String& suggestedFilename() const; + void setSuggestedFilename(const String&); + + int httpStatusCode() const; + void setHTTPStatusCode(int); + + const String& httpStatusText() const; + void setHTTPStatusText(const String&); + + String httpHeaderField(const String& name) const; + void setHTTPHeaderField(const String& name, const String& value); + const HTTPHeaderMap& httpHeaderFields() const; + + bool isMultipart() const { return mimeType() == "multipart/x-mixed-replace"; } + + bool isAttachment() const; + + void setExpirationDate(time_t); + time_t expirationDate() const; + + void setLastModifiedDate(time_t); + time_t lastModifiedDate() const; + + static bool compare(const ResourceResponse& a, const ResourceResponse& b); + + protected: + ResourceResponseBase() + : m_expectedContentLength(0) + , m_httpStatusCode(0) + , m_expirationDate(0) + , m_lastModifiedDate(0) + , m_isNull(true) + { + } + + ResourceResponseBase(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename) + : m_url(url) + , m_mimeType(mimeType) + , m_expectedContentLength(expectedLength) + , m_textEncodingName(textEncodingName) + , m_suggestedFilename(filename) + , m_httpStatusCode(0) + , m_expirationDate(0) + , m_lastModifiedDate(0) + , m_isNull(false) + { + } + + void lazyInit() const; + + // The ResourceResponse subclass may "shadow" this method to lazily initialize platform specific fields + void platformLazyInit() {} + + // The ResourceResponse subclass may "shadow" this method to compare platform specific fields + static bool platformCompare(const ResourceResponse& a, const ResourceResponse& b) { return true; } + + KURL m_url; + String m_mimeType; + long long m_expectedContentLength; + String m_textEncodingName; + String m_suggestedFilename; + int m_httpStatusCode; + String m_httpStatusText; + HTTPHeaderMap m_httpHeaderFields; + time_t m_expirationDate; + time_t m_lastModifiedDate; + bool m_isNull; + +}; + +inline bool operator==(const ResourceResponse& a, const ResourceResponse& b) { return ResourceResponseBase::compare(a, b); } +inline bool operator!=(const ResourceResponse& a, const ResourceResponse& b) { return !(a == b); } + +} // namespace WebCore + +#endif // ResourceResponseBase_h diff --git a/WebCore/platform/network/android/AuthenticationChallenge.h b/WebCore/platform/network/android/AuthenticationChallenge.h new file mode 100644 index 0000000..971bf97 --- /dev/null +++ b/WebCore/platform/network/android/AuthenticationChallenge.h @@ -0,0 +1,55 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" +#include "ResourceHandle.h" +#include <wtf/RefPtr.h> + +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) + : AuthenticationChallengeBase(protectionSpace, proposedCredential, previousFailureCount, response, error) + { + } + + ResourceHandle* sourceHandle() const { return m_sourceHandle.get(); } + + RefPtr<ResourceHandle> m_sourceHandle; +}; + +} + +#endif diff --git a/WebCore/platform/network/android/Cookie.cpp b/WebCore/platform/network/android/Cookie.cpp new file mode 100644 index 0000000..0b7aa45 --- /dev/null +++ b/WebCore/platform/network/android/Cookie.cpp @@ -0,0 +1,58 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 COMPUTER, INC. OR + * 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. + */ +#define LOG_TAG "Cookies" + +#include "config.h" +#include "JavaSharedClient.h" +#include "CookieClient.h" + +using namespace android; + +namespace WebCore { + + class Document; + + void setCookies(Document* , const KURL& url, const KURL& policyBaseURL, const String& value) + { + if (JavaSharedClient::GetCookieClient()) + JavaSharedClient::GetCookieClient()->setCookies(url, policyBaseURL, value); + } + + String cookies(const Document* , const KURL& url) + { + if (JavaSharedClient::GetCookieClient()) + return JavaSharedClient::GetCookieClient()->cookies(url); + return String(); + } + + bool cookiesEnabled(const Document* ) + { + if (JavaSharedClient::GetCookieClient()) + return JavaSharedClient::GetCookieClient()->cookiesEnabled(); + return false; + } + +} + diff --git a/WebCore/platform/network/android/CookieClient.h b/WebCore/platform/network/android/CookieClient.h new file mode 100644 index 0000000..4b6ffef --- /dev/null +++ b/WebCore/platform/network/android/CookieClient.h @@ -0,0 +1,47 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 COMPUTER, INC. OR + * 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 COOKIE_CLIENT_H +#define COOKIE_CLIENT_H + +#include "KURL.h" +#include "PlatformString.h" + +using namespace WebCore; + +namespace android { + + class CookieClient + { + public: + virtual ~CookieClient() {} + virtual void setCookies(const KURL& url, const KURL& docURL, const String& value) = 0; + virtual String cookies(const KURL& url) = 0; + virtual bool cookiesEnabled() = 0; + }; + +} +#endif + diff --git a/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp b/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp new file mode 100644 index 0000000..3e49fff --- /dev/null +++ b/WebCore/platform/network/android/NetworkStateNotifierAndroid.cpp @@ -0,0 +1,42 @@ +/* + * Copyright 2008, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 COMPUTER, INC. OR + * 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 "NetworkStateNotifier.h" + +namespace WebCore { + +void NetworkStateNotifier::networkStateChange(bool online) +{ + if (m_isOnLine == online) + return; + + m_isOnLine = online; + + if (m_networkStateChangedFunction) + m_networkStateChangedFunction(); +} + +} diff --git a/WebCore/platform/network/android/ResourceError.h b/WebCore/platform/network/android/ResourceError.h new file mode 100644 index 0000000..12a6323 --- /dev/null +++ b/WebCore/platform/network/android/ResourceError.h @@ -0,0 +1,49 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceError_h +#define ResourceError_h + +#include "ResourceErrorBase.h" + +namespace WebCore { + +class ResourceError : public ResourceErrorBase +{ +public: + ResourceError() + { + } + + ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) + { + } +}; + +} + +#endif // ResourceError_h_ diff --git a/WebCore/platform/network/android/ResourceHandleAndroid.cpp b/WebCore/platform/network/android/ResourceHandleAndroid.cpp new file mode 100644 index 0000000..4d9199a --- /dev/null +++ b/WebCore/platform/network/android/ResourceHandleAndroid.cpp @@ -0,0 +1,157 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 COMPUTER, INC. OR + * 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. + */ +#define LOG_TAG "WebCore" + +#include "config.h" +#include "ResourceHandle.h" + +#include "DocLoader.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameLoaderClientAndroid.h" +#include "NotImplemented.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "WebCoreFrameBridge.h" +#include "WebCoreResourceLoader.h" +#include "CString.h" + +using namespace android; + +namespace WebCore { + +ResourceHandleInternal::~ResourceHandleInternal() +{ + Release(m_loader); +} + +ResourceHandle::~ResourceHandle() +{ +} + +bool ResourceHandle::start(Frame* frame) +{ + WebCoreResourceLoader* loader; + bool highPriority = true; + CachedResource* r = d->m_request.getCachedResource(); + if (r) { + CachedResource::Type t = r->type(); + highPriority = !(t == CachedResource::ImageResource || + t == CachedResource::FontResource); + } + FrameLoaderClientAndroid* client = static_cast<FrameLoaderClientAndroid*> (frame->loader()->client()); + loader = client->webFrame()->startLoadingResource(this, d->m_request, highPriority, false); + + if (loader) { + Release(d->m_loader); + d->m_loader = loader; + } + + return loader != NULL; +} + +void ResourceHandle::cancel() +{ + if (d->m_loader) + d->m_loader->cancel(); +} + +PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() +{ + return 0; +} + +bool ResourceHandle::supportsBufferedData() +{ + // We don't support buffering data on the native side. + return false; +} + +void ResourceHandle::setDefersLoading(bool defers) +{ + notImplemented(); +} + +/* +* This static method is called to check to see if a POST response is in +* the cache. The JNI call through to the HTTP cache stored on the Java +* side may be slow, but is only used during a navigation to +* a POST response. +*/ +bool ResourceHandle::willLoadFromCache(ResourceRequest& request) +{ + // set the cache policy correctly, copied from + // network/mac/ResourceHandleMac.mm + request.setCachePolicy(ReturnCacheDataDontLoad); + return WebCoreResourceLoader::willLoadFromCache(request.url()); +} + +bool ResourceHandle::loadsBlocked() +{ + // FIXME, need to check whether connection pipe is blocked. + // return false for now + return false; +} + +// Class to handle synchronized loading of resources. +class SyncLoader : public ResourceHandleClient { +public: + SyncLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data) { + m_error = &error; + m_response = &response; + m_data = &data; + } + ~SyncLoader() {} + + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse& response) { + *m_response = response; + } + + virtual void didReceiveData(ResourceHandle*, const char* data, int len, int lengthReceived) { + m_data->append(data, len); + } + + virtual void didFail(ResourceHandle*, const ResourceError& error) { + *m_error = error; + } + +private: + ResourceError* m_error; + ResourceResponse* m_response; + Vector<char>* m_data; +}; + +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, + ResourceError& error, ResourceResponse& response, Vector<char>& data, + Frame* frame) +{ + SyncLoader s(error, response, data); + ResourceHandle h(request, &s, false, false, false); + // This blocks until the load is finished. + FrameLoaderClientAndroid* client = static_cast<FrameLoaderClientAndroid*> (frame->loader()->client()); + client->webFrame()->startLoadingResource(&h, request, true, true); +} + +} // namespace WebCore diff --git a/WebCore/platform/network/android/ResourceRequest.h b/WebCore/platform/network/android/ResourceRequest.h new file mode 100644 index 0000000..bc12600 --- /dev/null +++ b/WebCore/platform/network/android/ResourceRequest.h @@ -0,0 +1,93 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequest_h +#define ResourceRequest_h + +#include "CachedResource.h" +#include "ResourceRequestBase.h" + +namespace WebCore { + + struct ResourceRequest : ResourceRequestBase { + + ResourceRequest(const String& url) + : ResourceRequestBase(KURL(url), UseProtocolCachePolicy) + , m_cachedResource(0) +#ifdef ANDROID_USER_GESTURE + , m_wasUserGesture(true) +#endif + { + } + + ResourceRequest(const KURL& url) + : ResourceRequestBase(url, UseProtocolCachePolicy) + , m_cachedResource(0) +#ifdef ANDROID_USER_GESTURE + , m_wasUserGesture(true) +#endif + { + } + + ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy) + : ResourceRequestBase(url, policy) + , m_cachedResource(0) +#ifdef ANDROID_USER_GESTURE + , m_wasUserGesture(true) +#endif + { + setHTTPReferrer(referrer); + } + + ResourceRequest() + : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + , m_cachedResource(0) +#ifdef ANDROID_USER_GESTURE + , m_wasUserGesture(true) +#endif + { + } + + void doUpdatePlatformRequest() {} + void doUpdateResourceRequest() {} + void setCachedResource(CachedResource* r) { m_cachedResource = r; } + CachedResource* getCachedResource() const { return m_cachedResource; } +#ifdef ANDROID_USER_GESTURE + void setUserGesture(bool userGesture) { m_wasUserGesture = userGesture; } + bool userGesture() const { return m_wasUserGesture; } +#endif + private: + friend class ResourceRequestBase; + CachedResource* m_cachedResource; +#ifdef ANDROID_USER_GESTURE + bool m_wasUserGesture; +#endif + }; + +} // namespace WebCore + +#endif // ResourceRequest_h diff --git a/WebCore/platform/network/android/ResourceResponse.h b/WebCore/platform/network/android/ResourceResponse.h new file mode 100644 index 0000000..5249636 --- /dev/null +++ b/WebCore/platform/network/android/ResourceResponse.h @@ -0,0 +1,60 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponse_h +#define ResourceResponse_h + +#include "ResourceResponseBase.h" + +#include "NotImplemented.h" + +namespace WebCore { + +class ResourceResponse : public ResourceResponseBase { +public: + ResourceResponse() + : ResourceResponseBase() + { + } + + ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename) + : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename) + { + } + +private: + friend class ResourceResponseBase; + + void doUpdateResourceResponse() + { + notImplemented(); + } + +}; + +} // namespace WebCore + +#endif // ResourceResponse_h diff --git a/WebCore/platform/network/cf/AuthenticationCF.cpp b/WebCore/platform/network/cf/AuthenticationCF.cpp new file mode 100644 index 0000000..bb05a39 --- /dev/null +++ b/WebCore/platform/network/cf/AuthenticationCF.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "AuthenticationCF.h" + +#include "AuthenticationChallenge.h" +#include "Credential.h" +#include "ProtectionSpace.h" +#include "ResourceHandle.h" + +#include <CFNetwork/CFURLAuthChallengePriv.h> +#include <CFNetwork/CFURLCredentialPriv.h> +#include <CFNetwork/CFURLProtectionSpacePriv.h> + +namespace WebCore { + +AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace, + const Credential& proposedCredential, + unsigned previousFailureCount, + const ResourceResponse& response, + const ResourceError& error) + : AuthenticationChallengeBase(protectionSpace, + proposedCredential, + previousFailureCount, + response, + error) +{ +} + +AuthenticationChallenge::AuthenticationChallenge(CFURLAuthChallengeRef cfChallenge, + ResourceHandle* sourceHandle) + : AuthenticationChallengeBase(core(CFURLAuthChallengeGetProtectionSpace(cfChallenge)), + core(CFURLAuthChallengeGetProposedCredential(cfChallenge)), + CFURLAuthChallengeGetPreviousFailureCount(cfChallenge), + (CFURLResponseRef)CFURLAuthChallengeGetFailureResponse(cfChallenge), + CFURLAuthChallengeGetError(cfChallenge)) + , m_sourceHandle(sourceHandle) + , m_cfChallenge(cfChallenge) +{ +} + +bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b) +{ + if (a.sourceHandle() != b.sourceHandle()) + return false; + + if (a.cfURLAuthChallengeRef() != b.cfURLAuthChallengeRef()) + return false; + + return true; +} + +CFURLAuthChallengeRef createCF(const AuthenticationChallenge& coreChallenge) +{ + CFURLProtectionSpaceRef protectionSpace = createCF(coreChallenge.protectionSpace()); + CFURLCredentialRef credential = createCF(coreChallenge.proposedCredential()); + + CFURLAuthChallengeRef result = CFURLAuthChallengeCreate(0, protectionSpace, credential, + coreChallenge.previousFailureCount(), + coreChallenge.failureResponse().cfURLResponse(), + coreChallenge.error()); + CFRelease(protectionSpace); + CFRelease(credential); + return result; +} + +CFURLCredentialRef createCF(const Credential& coreCredential) +{ + CFURLCredentialPersistence persistence = kCFURLCredentialPersistenceNone; + switch (coreCredential.persistence()) { + case CredentialPersistenceNone: + break; + case CredentialPersistenceForSession: + persistence = kCFURLCredentialPersistenceForSession; + break; + case CredentialPersistencePermanent: + persistence = kCFURLCredentialPersistencePermanent; + break; + default: + ASSERT_NOT_REACHED(); + } + + CFStringRef user = coreCredential.user().createCFString(); + CFStringRef password = coreCredential.password().createCFString(); + CFURLCredentialRef result = CFURLCredentialCreate(0, user, password, 0, persistence); + CFRelease(user); + CFRelease(password); + + return result; +} + +CFURLProtectionSpaceRef createCF(const ProtectionSpace& coreSpace) +{ + CFURLProtectionSpaceServerType serverType = kCFURLProtectionSpaceServerHTTP; + switch (coreSpace.serverType()) { + case ProtectionSpaceServerHTTP: + serverType = kCFURLProtectionSpaceServerHTTP; + break; + case ProtectionSpaceServerHTTPS: + serverType = kCFURLProtectionSpaceServerHTTPS; + break; + case ProtectionSpaceServerFTP: + serverType = kCFURLProtectionSpaceServerFTP; + break; + case ProtectionSpaceServerFTPS: + serverType = kCFURLProtectionSpaceServerFTPS; + break; + case ProtectionSpaceProxyHTTP: + serverType = kCFURLProtectionSpaceProxyHTTP; + break; + case ProtectionSpaceProxyHTTPS: + serverType = kCFURLProtectionSpaceProxyHTTPS; + break; + case ProtectionSpaceProxyFTP: + serverType = kCFURLProtectionSpaceProxyFTP; + break; + case ProtectionSpaceProxySOCKS: + serverType = kCFURLProtectionSpaceProxySOCKS; + break; + default: + ASSERT_NOT_REACHED(); + } + + CFURLProtectionSpaceAuthenticationScheme scheme = kCFURLProtectionSpaceAuthenticationSchemeDefault; + switch (coreSpace.authenticationScheme()) { + case ProtectionSpaceAuthenticationSchemeDefault: + scheme = kCFURLProtectionSpaceAuthenticationSchemeDefault; + break; + case ProtectionSpaceAuthenticationSchemeHTTPBasic: + scheme = kCFURLProtectionSpaceAuthenticationSchemeHTTPBasic; + break; + case ProtectionSpaceAuthenticationSchemeHTTPDigest: + scheme = kCFURLProtectionSpaceAuthenticationSchemeHTTPDigest; + break; + case ProtectionSpaceAuthenticationSchemeHTMLForm: + scheme = kCFURLProtectionSpaceAuthenticationSchemeHTMLForm; + break; + case ProtectionSpaceAuthenticationSchemeNTLM: + scheme = kCFURLProtectionSpaceAuthenticationSchemeNTLM; + break; + case ProtectionSpaceAuthenticationSchemeNegotiate: + scheme = kCFURLProtectionSpaceAuthenticationSchemeNegotiate; + break; + default: + ASSERT_NOT_REACHED(); + } + + CFStringRef host = coreSpace.host().createCFString(); + CFStringRef realm = coreSpace.realm().createCFString(); + CFURLProtectionSpaceRef result = CFURLProtectionSpaceCreate(0, host, coreSpace.port(), serverType, realm, scheme); + CFRelease(host); + CFRelease(realm); + + return result; +} + +Credential core(CFURLCredentialRef cfCredential) +{ + if (!cfCredential) + return Credential(); + + CredentialPersistence persistence = CredentialPersistenceNone; + switch (CFURLCredentialGetPersistence(cfCredential)) { + case kCFURLCredentialPersistenceNone: + break; + case kCFURLCredentialPersistenceForSession: + persistence = CredentialPersistenceForSession; + break; + case kCFURLCredentialPersistencePermanent: + persistence = CredentialPersistencePermanent; + break; + default: + ASSERT_NOT_REACHED(); + } + + return Credential(CFURLCredentialGetUsername(cfCredential), CFURLCredentialCopyPassword(cfCredential), persistence); +} + +ProtectionSpace core(CFURLProtectionSpaceRef cfSpace) +{ + ProtectionSpaceServerType serverType = ProtectionSpaceServerHTTP; + + switch (CFURLProtectionSpaceGetServerType(cfSpace)) { + case kCFURLProtectionSpaceServerHTTP: + break; + case kCFURLProtectionSpaceServerHTTPS: + serverType = ProtectionSpaceServerHTTPS; + break; + case kCFURLProtectionSpaceServerFTP: + serverType = ProtectionSpaceServerFTP; + break; + case kCFURLProtectionSpaceServerFTPS: + serverType = ProtectionSpaceServerFTPS; + break; + case kCFURLProtectionSpaceProxyHTTP: + serverType = ProtectionSpaceProxyHTTP; + break; + case kCFURLProtectionSpaceProxyHTTPS: + serverType = ProtectionSpaceProxyHTTPS; + break; + case kCFURLProtectionSpaceProxyFTP: + serverType = ProtectionSpaceProxyFTP; + break; + case kCFURLProtectionSpaceProxySOCKS: + serverType = ProtectionSpaceProxySOCKS; + break; + default: + ASSERT_NOT_REACHED(); + } + + ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault; + + switch (CFURLProtectionSpaceGetAuthenticationScheme(cfSpace)) { + case kCFURLProtectionSpaceAuthenticationSchemeDefault: + scheme = ProtectionSpaceAuthenticationSchemeDefault; + break; + case kCFURLProtectionSpaceAuthenticationSchemeHTTPBasic: + scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic; + break; + case kCFURLProtectionSpaceAuthenticationSchemeHTTPDigest: + scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest; + break; + case kCFURLProtectionSpaceAuthenticationSchemeHTMLForm: + scheme = ProtectionSpaceAuthenticationSchemeHTMLForm; + break; + case kCFURLProtectionSpaceAuthenticationSchemeNTLM: + scheme = ProtectionSpaceAuthenticationSchemeNTLM; + break; + case kCFURLProtectionSpaceAuthenticationSchemeNegotiate: + scheme = ProtectionSpaceAuthenticationSchemeNegotiate; + break; + default: + ASSERT_NOT_REACHED(); + } + + return ProtectionSpace(CFURLProtectionSpaceGetHost(cfSpace), + CFURLProtectionSpaceGetPort(cfSpace), + serverType, + CFURLProtectionSpaceGetRealm(cfSpace), + scheme); +} + +}; diff --git a/WebCore/platform/network/cf/AuthenticationCF.h b/WebCore/platform/network/cf/AuthenticationCF.h new file mode 100644 index 0000000..681e71f --- /dev/null +++ b/WebCore/platform/network/cf/AuthenticationCF.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationCF_h +#define AuthenticationCF_h + +typedef struct _CFURLAuthChallenge* CFURLAuthChallengeRef; +typedef struct _CFURLCredential* CFURLCredentialRef; +typedef struct _CFURLProtectionSpace* CFURLProtectionSpaceRef; + +namespace WebCore { + +class AuthenticationChallenge; +class Credential; +class ProtectionSpace; + +CFURLAuthChallengeRef createCF(const AuthenticationChallenge&); +CFURLCredentialRef createCF(const Credential&); +CFURLProtectionSpaceRef createCF(const ProtectionSpace&); + +Credential core(CFURLCredentialRef); +ProtectionSpace core(CFURLProtectionSpaceRef); + + +} + +#endif diff --git a/WebCore/platform/network/cf/AuthenticationChallenge.h b/WebCore/platform/network/cf/AuthenticationChallenge.h new file mode 100644 index 0000000..9697d7e --- /dev/null +++ b/WebCore/platform/network/cf/AuthenticationChallenge.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" +#include "ResourceHandle.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); + + 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; + RetainPtr<CFURLAuthChallengeRef> m_cfChallenge; +}; + +} + +#endif diff --git a/WebCore/platform/network/cf/DNSCFNet.cpp b/WebCore/platform/network/cf/DNSCFNet.cpp new file mode 100644 index 0000000..e571494 --- /dev/null +++ b/WebCore/platform/network/cf/DNSCFNet.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 Collin Jackson <collinj@webkit.org> + * + * 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 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 COMPUTER, INC. OR + * 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 "DNS.h" + +#include "NotImplemented.h" + +namespace WebCore { + +void prefetchDNS(const String& hostname) +{ + notImplemented(); +} + +} diff --git a/WebCore/platform/network/cf/FormDataStreamCFNet.cpp b/WebCore/platform/network/cf/FormDataStreamCFNet.cpp new file mode 100644 index 0000000..71fbfe7 --- /dev/null +++ b/WebCore/platform/network/cf/FormDataStreamCFNet.cpp @@ -0,0 +1,422 @@ +/* + * Copyright (C) 2005, 2006, 2007 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +/* originally written by Becky Willrich, additional code by Darin Adler */ + +#include "config.h" +#include "FormDataStreamCFNet.h" + +#include "CString.h" +#include "FileSystem.h" +#include "FormData.h" +#include <CFNetwork/CFURLRequestPriv.h> +#include <CoreFoundation/CFStreamAbstract.h> +#include <WebKitSystemInterface/WebKitSystemInterface.h> +#include <sys/types.h> +#include <wtf/Assertions.h> +#include <wtf/HashMap.h> +#include <wtf/RetainPtr.h> + +#define USE_V1_CFSTREAM_CALLBACKS +#ifdef USE_V1_CFSTREAM_CALLBACKS +typedef CFReadStreamCallBacksV1 WCReadStreamCallBacks; +#else +typedef CFReadStreamCallBacks WCReadStreamCallBacks; +#endif + +namespace WebCore { + +static HashMap<CFReadStreamRef, RefPtr<FormData> >& getStreamFormDatas() +{ + static HashMap<CFReadStreamRef, RefPtr<FormData> > streamFormDatas; + return streamFormDatas; +} + +static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context); + +struct FormStreamFields { + CFMutableSetRef scheduledRunLoopPairs; + Vector<FormDataElement> remainingElements; // in reverse order + CFReadStreamRef currentStream; + char* currentData; + CFReadStreamRef formStream; +}; + +struct SchedulePair { + CFRunLoopRef runLoop; + CFStringRef mode; +}; + +static const void* pairRetain(CFAllocatorRef alloc, const void* value) +{ + const SchedulePair* pair = static_cast<const SchedulePair*>(value); + + SchedulePair* result = new SchedulePair; + CFRetain(pair->runLoop); + result->runLoop = pair->runLoop; + result->mode = CFStringCreateCopy(alloc, pair->mode); + return result; +} + +static void pairRelease(CFAllocatorRef alloc, const void* value) +{ + const SchedulePair* pair = static_cast<const SchedulePair*>(value); + + CFRelease(pair->runLoop); + CFRelease(pair->mode); + delete pair; +} + +static Boolean pairEqual(const void* a, const void* b) +{ + const SchedulePair* pairA = static_cast<const SchedulePair*>(a); + const SchedulePair* pairB = static_cast<const SchedulePair*>(b); + + return pairA->runLoop == pairB->runLoop && CFEqual(pairA->mode, pairB->mode); +} + +static CFHashCode pairHash(const void* value) +{ + const SchedulePair* pair = static_cast<const SchedulePair*>(value); + + return (CFHashCode)pair->runLoop ^ CFHash(pair->mode); +} + +static void closeCurrentStream(FormStreamFields *form) +{ + if (form->currentStream) { + CFReadStreamClose(form->currentStream); + CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, NULL, NULL); + CFRelease(form->currentStream); + form->currentStream = NULL; + } + if (form->currentData) { + fastFree(form->currentData); + form->currentData = 0; + } +} + +static void scheduleWithPair(const void* value, void* context) +{ + const SchedulePair* pair = static_cast<const SchedulePair*>(value); + CFReadStreamRef stream = (CFReadStreamRef)context; + + CFReadStreamScheduleWithRunLoop(stream, pair->runLoop, pair->mode); +} + +static void advanceCurrentStream(FormStreamFields *form) +{ + closeCurrentStream(form); + + if (form->remainingElements.isEmpty()) + return; + + // Create the new stream. + FormDataElement& nextInput = form->remainingElements.last(); + if (nextInput.m_type == FormDataElement::data) { + size_t size = nextInput.m_data.size(); + char* data = nextInput.m_data.releaseBuffer(); + form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull); + form->currentData = data; + } else { + CFStringRef filename = nextInput.m_filename.createCFString(); +#if PLATFORM(WIN) + CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLWindowsPathStyle, FALSE); +#else + CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLPOSIXPathStyle, FALSE); +#endif + CFRelease(filename); + form->currentStream = CFReadStreamCreateWithFile(0, fileURL); + CFRelease(fileURL); + } + form->remainingElements.removeLast(); + + // Set up the callback. + CFStreamClientContext context = { 0, form, NULL, NULL, NULL }; + CFReadStreamSetClient(form->currentStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, + formEventCallback, &context); + + // Schedule with the current set of run loops. + CFSetApplyFunction(form->scheduledRunLoopPairs, scheduleWithPair, form->currentStream); +} + +static void openNextStream(FormStreamFields* form) +{ + // Skip over any streams we can't open. + // For some purposes we might want to return an error, but the current CFURLConnection + // can't really do anything useful with an error at this point, so this is better. + advanceCurrentStream(form); + while (form->currentStream && !CFReadStreamOpen(form->currentStream)) + advanceCurrentStream(form); +} + +static void* formCreate(CFReadStreamRef stream, void* context) +{ + FormData* formData = static_cast<FormData*>(context); + + CFSetCallBacks runLoopAndModeCallBacks = { 0, pairRetain, pairRelease, NULL, pairEqual, pairHash }; + + FormStreamFields* newInfo = new FormStreamFields; + newInfo->scheduledRunLoopPairs = CFSetCreateMutable(0, 0, &runLoopAndModeCallBacks); + newInfo->currentStream = NULL; + newInfo->currentData = 0; + newInfo->formStream = stream; // Don't retain. That would create a reference cycle. + + // Append in reverse order since we remove elements from the end. + size_t size = formData->elements().size(); + newInfo->remainingElements.reserveCapacity(size); + for (size_t i = 0; i < size; ++i) + newInfo->remainingElements.append(formData->elements()[size - i - 1]); + + getStreamFormDatas().set(stream, adoptRef(formData)); + + return newInfo; +} + +static void formFinalize(CFReadStreamRef stream, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + getStreamFormDatas().remove(stream); + + closeCurrentStream(form); + CFRelease(form->scheduledRunLoopPairs); + delete form; +} + +static Boolean formOpen(CFReadStreamRef stream, CFStreamError* error, Boolean* openComplete, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + openNextStream(form); + + *openComplete = TRUE; + error->error = 0; + return TRUE; +} + +static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLength, CFStreamError* error, Boolean* atEOF, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + while (form->currentStream) { + CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bufferLength); + if (bytesRead < 0) { + *error = CFReadStreamGetError(form->currentStream); + return -1; + } + if (bytesRead > 0) { + error->error = 0; + *atEOF = FALSE; + return bytesRead; + } + openNextStream(form); + } + + error->error = 0; + *atEOF = TRUE; + return 0; +} + +static Boolean formCanRead(CFReadStreamRef stream, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + while (form->currentStream && CFReadStreamGetStatus(form->currentStream) == kCFStreamStatusAtEnd) { + openNextStream(form); + } + if (!form->currentStream) { + CFReadStreamSignalEvent(stream, kCFStreamEventEndEncountered, 0); + return FALSE; + } + return CFReadStreamHasBytesAvailable(form->currentStream); +} + +static void formClose(CFReadStreamRef stream, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + closeCurrentStream(form); +} + +static void formSchedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + if (form->currentStream) + CFReadStreamScheduleWithRunLoop(form->currentStream, runLoop, runLoopMode); + SchedulePair pair = { runLoop, runLoopMode }; + CFSetAddValue(form->scheduledRunLoopPairs, &pair); +} + +static void formUnschedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + if (form->currentStream) + CFReadStreamUnscheduleFromRunLoop(form->currentStream, runLoop, runLoopMode); + SchedulePair pair = { runLoop, runLoopMode }; + CFSetRemoveValue(form->scheduledRunLoopPairs, &pair); +} + +static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + switch (type) { + case kCFStreamEventHasBytesAvailable: + CFReadStreamSignalEvent(form->formStream, kCFStreamEventHasBytesAvailable, 0); + break; + case kCFStreamEventErrorOccurred: { + CFStreamError readStreamError = CFReadStreamGetError(stream); + CFReadStreamSignalEvent(form->formStream, kCFStreamEventErrorOccurred, &readStreamError); + break; + } + case kCFStreamEventEndEncountered: + openNextStream(form); + if (!form->currentStream) + CFReadStreamSignalEvent(form->formStream, kCFStreamEventEndEncountered, 0); + break; + case kCFStreamEventNone: + LOG_ERROR("unexpected kCFStreamEventNone"); + break; + case kCFStreamEventOpenCompleted: + LOG_ERROR("unexpected kCFStreamEventOpenCompleted"); + break; + case kCFStreamEventCanAcceptBytes: + LOG_ERROR("unexpected kCFStreamEventCanAcceptBytes"); + break; + } +} + +void setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> formData) +{ + if (!formData) { + if (wkCanAccessCFURLRequestHTTPBodyParts()) + wkCFURLRequestSetHTTPRequestBodyParts(request, 0); + return; + } + + size_t count = formData->elements().size(); + + if (count == 0) + return; + + // Handle the common special case of one piece of form data, with no files. + if (count == 1) { + const FormDataElement& element = formData->elements()[0]; + if (element.m_type == FormDataElement::data) { + CFDataRef data = CFDataCreate(0, reinterpret_cast<const UInt8 *>(element.m_data.data()), element.m_data.size()); + CFURLRequestSetHTTPRequestBody(request, data); + CFRelease(data); + return; + } + } + + if (wkCanAccessCFURLRequestHTTPBodyParts()) { + RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks)); + + for (size_t i = 0; i < count; ++i) { + const FormDataElement& element = formData->elements()[i]; + if (element.m_type == FormDataElement::data) { + RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, reinterpret_cast<const UInt8*>(element.m_data.data()), element.m_data.size())); + CFArrayAppendValue(array.get(), data.get()); + } else { + RetainPtr<CFStringRef> filename(AdoptCF, element.m_filename.createCFString()); + CFArrayAppendValue(array.get(), filename.get()); + } + } + + wkCFURLRequestSetHTTPRequestBodyParts(request, array.get()); + return; + } + + // Precompute the content length so CFURLConnection doesn't use chunked mode. + bool haveLength = true; + long long length = 0; + for (size_t i = 0; i < count; ++i) { + const FormDataElement& element = formData->elements()[i]; + if (element.m_type == FormDataElement::data) + length += element.m_data.size(); + else { + long long size; + if (getFileSize(element.m_filename, size)) + length += size; + else + haveLength = false; + } + } + + if (haveLength) { + CFStringRef lengthStr = CFStringCreateWithFormat(0, 0, CFSTR("%lld"), length); + CFURLRequestSetHTTPHeaderFieldValue(request, CFSTR("Content-Length"), lengthStr); + CFRelease(lengthStr); + } + + static WCReadStreamCallBacks formDataStreamCallbacks = + { 1, formCreate, formFinalize, 0, formOpen, 0, formRead, 0, formCanRead, formClose, 0, 0, 0, formSchedule, formUnschedule }; + + CFReadStreamRef stream = CFReadStreamCreate(0, (CFReadStreamCallBacks *)&formDataStreamCallbacks, formData.releaseRef()); + CFURLRequestSetHTTPRequestBodyStream(request, stream); + CFRelease(stream); +} + +PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request) +{ + if (RetainPtr<CFDataRef> bodyData = CFURLRequestCopyHTTPRequestBody(request)) + return FormData::create(CFDataGetBytePtr(bodyData.get()), CFDataGetLength(bodyData.get())); + + if (wkCanAccessCFURLRequestHTTPBodyParts()) { + if (RetainPtr<CFArrayRef> bodyParts = wkCFURLRequestCopyHTTPRequestBodyParts(request)) { + RefPtr<FormData> formData = FormData::create(); + + CFIndex count = CFArrayGetCount(bodyParts.get()); + for (CFIndex i = 0; i < count; i++) { + CFTypeRef bodyPart = CFArrayGetValueAtIndex(bodyParts.get(), i); + CFTypeID typeID = CFGetTypeID(bodyPart); + if (typeID == CFStringGetTypeID()) { + String filename = (CFStringRef)bodyPart; + formData->appendFile(filename); + } else if (typeID == CFDataGetTypeID()) { + CFDataRef data = (CFDataRef)bodyPart; + formData->appendData(CFDataGetBytePtr(data), CFDataGetLength(data)); + } else + ASSERT_NOT_REACHED(); + } + return formData.release(); + } + } else { + if (RetainPtr<CFReadStreamRef> bodyStream = CFURLRequestCopyHTTPRequestBodyStream(request)) + return getStreamFormDatas().get(bodyStream.get()); + } + + // FIXME: what to do about arbitrary body streams? + return 0; +} + +} diff --git a/WebCore/platform/network/cf/FormDataStreamCFNet.h b/WebCore/platform/network/cf/FormDataStreamCFNet.h new file mode 100644 index 0000000..254a2cd --- /dev/null +++ b/WebCore/platform/network/cf/FormDataStreamCFNet.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2005, 2006, 2007 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 FormDataStreamCFNet_h_ +#define FormDataStreamCFNet_h_ + +#include <CoreFoundation/CoreFoundation.h> +#include <wtf/Forward.h> + +typedef struct _CFURLRequest* CFMutableURLRequestRef; +typedef const struct _CFURLRequest* CFURLRequestRef; + +namespace WebCore { + class FormData; + void setHTTPBody(CFMutableURLRequestRef, PassRefPtr<FormData>); + PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef); +} + +#endif FormDataStreamCFNet_h_ diff --git a/WebCore/platform/network/cf/ResourceError.h b/WebCore/platform/network/cf/ResourceError.h new file mode 100644 index 0000000..10f1208 --- /dev/null +++ b/WebCore/platform/network/cf/ResourceError.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceError_h +#define ResourceError_h + +#include "ResourceErrorBase.h" + +#include <wtf/RetainPtr.h> +#include <CoreFoundation/CFStream.h> + +namespace WebCore { + +class ResourceError : public ResourceErrorBase { +public: + ResourceError() + : m_dataIsUpToDate(true) + { + } + + ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) + , m_dataIsUpToDate(true) + { + } + + ResourceError(CFStreamError error); + + ResourceError(CFErrorRef error) + : m_dataIsUpToDate(false) + , m_platformError(error) + { + m_isNull = !error; + } + + operator CFErrorRef() const; + operator CFStreamError() const; + +private: + friend class ResourceErrorBase; + + void platformLazyInit(); + static bool platformCompare(const ResourceError& a, const ResourceError& b); + + bool m_dataIsUpToDate; + mutable RetainPtr<CFErrorRef> m_platformError; +}; + +} // namespace WebCore + +#endif // ResourceError_h_ diff --git a/WebCore/platform/network/cf/ResourceErrorCF.cpp b/WebCore/platform/network/cf/ResourceErrorCF.cpp new file mode 100644 index 0000000..8e82cd5 --- /dev/null +++ b/WebCore/platform/network/cf/ResourceErrorCF.cpp @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "KURL.h" +#include "ResourceError.h" + +#if USE(CFNETWORK) + +// FIXME: Once <rdar://problem/5050881> is fixed in open source we +// can remove this extern "C" +extern "C" { +#include <CFNetwork/CFNetworkErrors.h> +} + +#include <CoreFoundation/CFError.h> +#include <WTF/RetainPtr.h> + +namespace WebCore { + +const CFStringRef failingURLStringKey = CFSTR("NSErrorFailingURLStringKey"); +const CFStringRef failingURLKey = CFSTR("NSErrorFailingURLKey"); + +// FIXME: Once <rdar://problem/5050841> is fixed we can remove this constructor. +ResourceError::ResourceError(CFStreamError error) + : m_dataIsUpToDate(true) +{ + m_isNull = false; + m_errorCode = error.error; + + switch(error.domain) { + case kCFStreamErrorDomainCustom: + m_domain ="NSCustomErrorDomain"; + break; + case kCFStreamErrorDomainPOSIX: + m_domain = "NSPOSIXErrorDomain"; + break; + case kCFStreamErrorDomainMacOSStatus: + m_domain = "NSOSStatusErrorDomain"; + break; + } +} + +void ResourceError::platformLazyInit() +{ + if (m_dataIsUpToDate) + return; + + if (!m_platformError) + return; + + CFStringRef domain = CFErrorGetDomain(m_platformError.get()); + if (domain == kCFErrorDomainMach || domain == kCFErrorDomainCocoa) + m_domain ="NSCustomErrorDomain"; + else if (domain == kCFErrorDomainCFNetwork) + m_domain = "CFURLErrorDomain"; + else if (domain == kCFErrorDomainPOSIX) + m_domain = "NSPOSIXErrorDomain"; + else if (domain == kCFErrorDomainOSStatus) + m_domain = "NSOSStatusErrorDomain"; + else if (domain == kCFErrorDomainWinSock) + m_domain = "kCFErrorDomainWinSock"; + + m_errorCode = CFErrorGetCode(m_platformError.get()); + + RetainPtr<CFDictionaryRef> userInfo(AdoptCF, CFErrorCopyUserInfo(m_platformError.get())); + if (userInfo.get()) { + CFStringRef failingURLString = (CFStringRef) CFDictionaryGetValue(userInfo.get(), failingURLStringKey); + if (failingURLString) + m_failingURL = String(failingURLString); + else { + CFURLRef failingURL = (CFURLRef) CFDictionaryGetValue(userInfo.get(), failingURLKey); + if (failingURL) { + RetainPtr<CFURLRef> absoluteURLRef(AdoptCF, CFURLCopyAbsoluteURL(failingURL)); + if (absoluteURLRef.get()) { + failingURLString = CFURLGetString(absoluteURLRef.get()); + m_failingURL = String(failingURLString); + } + } + } + m_localizedDescription = (CFStringRef) CFDictionaryGetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey); + } + + m_dataIsUpToDate = true; +} + +bool ResourceError::platformCompare(const ResourceError& a, const ResourceError& b) +{ + return (CFErrorRef)a == (CFErrorRef)b; +} + +ResourceError::operator CFErrorRef() const +{ + if (m_isNull) { + ASSERT(!m_platformError); + return nil; + } + + if (!m_platformError) { + RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + if (!m_localizedDescription.isEmpty()) { + RetainPtr<CFStringRef> localizedDescriptionString(AdoptCF, m_localizedDescription.createCFString()); + CFDictionarySetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey, localizedDescriptionString.get()); + } + + if (!m_failingURL.isEmpty()) { + RetainPtr<CFStringRef> failingURLString(AdoptCF, m_failingURL.createCFString()); + CFDictionarySetValue(userInfo.get(), failingURLStringKey, failingURLString.get()); + RetainPtr<CFURLRef> url(AdoptCF, KURL(m_failingURL).createCFURL()); + CFDictionarySetValue(userInfo.get(), failingURLKey, url.get()); + } + + RetainPtr<CFStringRef> domainString(AdoptCF, m_domain.createCFString()); + m_platformError.adoptCF(CFErrorCreate(0, domainString.get(), m_errorCode, userInfo.get())); + } + + return m_platformError.get(); +} + +ResourceError::operator CFStreamError() const +{ + lazyInit(); + + CFStreamError result; + result.error = m_errorCode; + + if (m_domain == "NSCustomErrorDomain") + result.domain = kCFStreamErrorDomainCustom; + else if (m_domain == "NSPOSIXErrorDomain") + result.domain = kCFStreamErrorDomainPOSIX; + else if (m_domain == "NSOSStatusErrorDomain") + result.domain = kCFStreamErrorDomainMacOSStatus; + else + ASSERT_NOT_REACHED(); + + return result; +} + +} // namespace WebCore + +#endif // USE(CFNETWORK) diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp new file mode 100644 index 0000000..fa7947f --- /dev/null +++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp @@ -0,0 +1,443 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" + +#include "AuthenticationCF.h" +#include "AuthenticationChallenge.h" +#include "CookieStorageWin.h" +#include "CString.h" +#include "DocLoader.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "Logging.h" +#include "NotImplemented.h" +#include "ResourceError.h" +#include "ResourceResponse.h" + +#include <wtf/HashMap.h> +#include <wtf/Threading.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <process.h> // for _beginthread() + +#include <CFNetwork/CFNetwork.h> +#include <WebKitSystemInterface/WebKitSystemInterface.h> + +namespace WebCore { + +static HashSet<String>& allowsAnyHTTPSCertificateHosts() +{ + static HashSet<String> hosts; + + return hosts; +} + +static HashMap<String, RetainPtr<CFDataRef> >& clientCerts() +{ + static HashMap<String, RetainPtr<CFDataRef> > certs; + return certs; +} + +CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo) +{ + ResourceHandle* handle = (ResourceHandle*)clientInfo; + + if (!cfRedirectResponse) { + CFRetain(cfRequest); + return cfRequest; + } + + LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); + + ResourceRequest request(cfRequest); + if (handle->client()) + handle->client()->willSendRequest(handle, request, cfRedirectResponse); + + cfRequest = request.cfURLRequest(); + + CFRetain(cfRequest); + return cfRequest; +} + +void didReceiveResponse(CFURLConnectionRef conn, CFURLResponseRef cfResponse, const void* clientInfo) +{ + ResourceHandle* handle = (ResourceHandle*)clientInfo; + + LOG(Network, "CFNet - didReceiveResponse(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); + + if (handle->client()) + handle->client()->didReceiveResponse(handle, cfResponse); +} + +void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLength, const void* clientInfo) +{ + ResourceHandle* handle = (ResourceHandle*)clientInfo; + const UInt8* bytes = CFDataGetBytePtr(data); + CFIndex length = CFDataGetLength(data); + + LOG(Network, "CFNet - didReceiveData(conn=%p, handle=%p, bytes=%d) (%s)", conn, handle, length, handle->request().url().string().utf8().data()); + + if (handle->client()) + handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength); +} + +void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo) +{ + ResourceHandle* handle = (ResourceHandle*)clientInfo; + + LOG(Network, "CFNet - didFinishLoading(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data()); + + if (handle->client()) + handle->client()->didFinishLoading(handle); +} + +void didFail(CFURLConnectionRef conn, CFErrorRef error, const void* clientInfo) +{ + ResourceHandle* handle = (ResourceHandle*)clientInfo; + + LOG(Network, "CFNet - didFail(conn=%p, handle=%p, error = %p) (%s)", conn, handle, error, handle->request().url().string().utf8().data()); + + if (handle->client()) + handle->client()->didFail(handle, ResourceError(error)); +} + +CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef conn, CFCachedURLResponseRef cachedResponse, const void* clientInfo) +{ + ResourceHandle* handle = (ResourceHandle*)clientInfo; + + CacheStoragePolicy policy = static_cast<CacheStoragePolicy>(CFCachedURLResponseGetStoragePolicy(cachedResponse)); + + if (handle->client()) + handle->client()->willCacheResponse(handle, policy); + + if (static_cast<CFURLCacheStoragePolicy>(policy) != CFCachedURLResponseGetStoragePolicy(cachedResponse)) + cachedResponse = CFCachedURLResponseCreateWithUserInfo(kCFAllocatorDefault, + CFCachedURLResponseGetWrappedResponse(cachedResponse), + CFCachedURLResponseGetReceiverData(cachedResponse), + CFCachedURLResponseGetUserInfo(cachedResponse), + static_cast<CFURLCacheStoragePolicy>(policy)); + CFRetain(cachedResponse); + + return cachedResponse; +} + +void didReceiveChallenge(CFURLConnectionRef conn, CFURLAuthChallengeRef challenge, const void* clientInfo) +{ + ResourceHandle* handle = (ResourceHandle*)clientInfo; + ASSERT(handle); + LOG(Network, "CFNet - didReceiveChallenge(conn=%p, handle=%p (%s)", conn, handle, handle->request().url().string().utf8().data()); + + handle->didReceiveAuthenticationChallenge(AuthenticationChallenge(challenge, handle)); +} + +void addHeadersFromHashMap(CFMutableURLRequestRef request, const HTTPHeaderMap& requestHeaders) +{ + if (!requestHeaders.size()) + return; + + HTTPHeaderMap::const_iterator end = requestHeaders.end(); + for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) { + CFStringRef key = it->first.createCFString(); + CFStringRef value = it->second.createCFString(); + CFURLRequestSetHTTPHeaderFieldValue(request, key, value); + CFRelease(key); + CFRelease(value); + } +} + +ResourceHandleInternal::~ResourceHandleInternal() +{ + if (m_connection) { + LOG(Network, "CFNet - Cancelling connection %p (%s)", m_connection, m_request.url().string().utf8().data()); + CFURLConnectionCancel(m_connection.get()); + } +} + +ResourceHandle::~ResourceHandle() +{ + LOG(Network, "CFNet - Destroying job %p (%s)", this, d->m_request.url().string().utf8().data()); +} + +CFArrayRef arrayFromFormData(const FormData& d) +{ + size_t size = d.elements().size(); + CFMutableArrayRef a = CFArrayCreateMutable(0, d.elements().size(), &kCFTypeArrayCallBacks); + for (size_t i = 0; i < size; ++i) { + const FormDataElement& e = d.elements()[i]; + if (e.m_type == FormDataElement::data) { + CFDataRef data = CFDataCreate(0, (const UInt8*)e.m_data.data(), e.m_data.size()); + CFArrayAppendValue(a, data); + CFRelease(data); + } else { + ASSERT(e.m_type == FormDataElement::encodedFile); + CFStringRef filename = e.m_filename.createCFString(); + CFArrayAppendValue(a, filename); + CFRelease(filename); + } + } + 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, "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()); + + if (!shouldContentSniff) + wkSetCFURLRequestShouldContentSniff(newRequest, false); + + RetainPtr<CFMutableDictionaryRef> sslProps; + + if (allowsAnyHTTPSCertificateHosts().contains(request.url().host().lower())) { + sslProps.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); + CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue); + } + + HashMap<String, RetainPtr<CFDataRef> >::iterator clientCert = clientCerts().find(request.url().host().lower()); + if (clientCert != clientCerts().end()) { + if (!sslProps) + sslProps.adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + wkSetClientCertificateInSSLProperties(sslProps.get(), (clientCert->second).get()); + } + + if (sslProps) + CFURLRequestSetSSLProperties(newRequest, sslProps.get()); + + if (CFHTTPCookieStorageRef cookieStorage = currentCookieStorage()) { + CFURLRequestSetHTTPCookieStorage(newRequest, cookieStorage); + CFURLRequestSetHTTPCookieStorageAcceptPolicy(newRequest, CFHTTPCookieStorageGetCookieAcceptPolicy(cookieStorage)); + } + + return newRequest; +} + +bool ResourceHandle::start(Frame* frame) +{ + // If we are no longer attached to a Page, this must be an attempted load from an + // onUnload handler, so let's just block it. + if (!frame->page()) + return false; + + RetainPtr<CFURLRequestRef> request(AdoptCF, makeFinalRequest(d->m_request, d->m_shouldContentSniff)); + + // CFURLConnection Callback API currently at version 1 + const int CFURLConnectionClientVersion = 1; + CFURLConnectionClient client = {CFURLConnectionClientVersion, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge}; + + d->m_connection.adoptCF(CFURLConnectionCreate(0, request.get(), &client)); + + CFURLConnectionScheduleWithCurrentMessageQueue(d->m_connection.get()); + CFURLConnectionScheduleDownloadWithRunLoop(d->m_connection.get(), loaderRunLoop(), kCFRunLoopDefaultMode); + CFURLConnectionStart(d->m_connection.get()); + + LOG(Network, "CFNet - Starting URL %s (handle=%p, conn=%p)", d->m_request.url().string().utf8().data(), this, d->m_connection); + + return true; +} + +void ResourceHandle::cancel() +{ + if (d->m_connection) { + CFURLConnectionCancel(d->m_connection.get()); + d->m_connection = 0; + } +} + +PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() +{ + ASSERT_NOT_REACHED(); + return 0; +} + +bool ResourceHandle::supportsBufferedData() +{ + return false; +} + +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()); + + d->m_currentCFChallenge = challenge.cfURLAuthChallengeRef(); + d->m_currentWebChallenge = AuthenticationChallenge(d->m_currentCFChallenge, this); + + if (client()) + client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge); +} + +void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) +{ + LOG(Network, "CFNet - receivedCredential()"); + ASSERT(!challenge.isNull()); + ASSERT(challenge.cfURLAuthChallengeRef()); + if (challenge != d->m_currentWebChallenge) + return; + + CFURLCredentialRef cfCredential = createCF(credential); + CFURLConnectionUseCredential(d->m_connection.get(), cfCredential, challenge.cfURLAuthChallengeRef()); + CFRelease(cfCredential); + + clearAuthentication(); +} + +void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& challenge) +{ + LOG(Network, "CFNet - receivedRequestToContinueWithoutCredential()"); + ASSERT(!challenge.isNull()); + ASSERT(challenge.cfURLAuthChallengeRef()); + if (challenge != d->m_currentWebChallenge) + return; + + CFURLConnectionUseCredential(d->m_connection.get(), 0, challenge.cfURLAuthChallengeRef()); + + clearAuthentication(); +} + +void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challenge) +{ + LOG(Network, "CFNet - receivedCancellation()"); + if (challenge != d->m_currentWebChallenge) + return; + + if (client()) + client()->receivedCancellation(this, challenge); +} + +CFURLConnectionRef ResourceHandle::connection() const +{ + return d->m_connection.get(); +} + +CFURLConnectionRef ResourceHandle::releaseConnectionForDownload() +{ + LOG(Network, "CFNet - Job %p releasing connection %p for download", this, d->m_connection.get()); + return d->m_connection.releaseRef(); +} + +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& vector, Frame*) +{ + ASSERT(!request.isEmpty()); + CFURLResponseRef cfResponse = 0; + CFErrorRef cfError = 0; + RetainPtr<CFURLRequestRef> cfRequest(AdoptCF, makeFinalRequest(request, true)); + + CFDataRef data = CFURLConnectionSendSynchronousRequest(cfRequest.get(), &cfResponse, &cfError, request.timeoutInterval()); + + if (cfError) { + error = cfError; + CFRelease(cfError); + + response = ResourceResponse(request.url(), String(), 0, String(), String()); + response.setHTTPStatusCode(404); + } else { + response = cfResponse; + if (cfResponse) + CFRelease(cfResponse); + } + + if (data) { + ASSERT(vector.isEmpty()); + vector.append(CFDataGetBytePtr(data), CFDataGetLength(data)); + CFRelease(data); + } +} + +void ResourceHandle::setHostAllowsAnyHTTPSCertificate(const String& host) +{ + allowsAnyHTTPSCertificateHosts().add(host.lower()); +} + +void ResourceHandle::setClientCertificate(const String& host, CFDataRef cert) +{ + clientCerts().set(host.lower(), cert); +} + +void ResourceHandle::setDefersLoading(bool defers) +{ + if (!d->m_connection) + return; + + if (defers) + CFURLConnectionHalt(d->m_connection.get()); + else + CFURLConnectionResume(d->m_connection.get()); +} + +bool ResourceHandle::loadsBlocked() +{ + return false; +} + +bool ResourceHandle::willLoadFromCache(ResourceRequest&) +{ + // Not having this function means that we'll ask the user about re-posting a form + // even when we go back to a page that's still in the cache. + notImplemented(); + return false; +} + +} // namespace WebCore diff --git a/WebCore/platform/network/cf/ResourceRequest.h b/WebCore/platform/network/cf/ResourceRequest.h new file mode 100644 index 0000000..a4e9749 --- /dev/null +++ b/WebCore/platform/network/cf/ResourceRequest.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequest_h +#define ResourceRequest_h + +#include "ResourceRequestBase.h" + +#include <wtf/RetainPtr.h> +typedef const struct _CFURLRequest* CFURLRequestRef; + +namespace WebCore { + + struct ResourceRequest : ResourceRequestBase { + + ResourceRequest(const String& url) + : ResourceRequestBase(KURL(url), UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url) + : ResourceRequestBase(url, UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy) + : ResourceRequestBase(url, policy) + { + setHTTPReferrer(referrer); + } + + ResourceRequest() + : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + { + } + + ResourceRequest(CFURLRequestRef cfRequest) + : ResourceRequestBase() + , m_cfRequest(cfRequest) { } + + CFURLRequestRef cfURLRequest() const; + + private: + friend struct ResourceRequestBase; + + void doUpdatePlatformRequest(); + void doUpdateResourceRequest(); + + RetainPtr<CFURLRequestRef> m_cfRequest; + }; + +} // namespace WebCore + +#endif // ResourceRequest_h diff --git a/WebCore/platform/network/cf/ResourceRequestCFNet.cpp b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp new file mode 100644 index 0000000..b73df13 --- /dev/null +++ b/WebCore/platform/network/cf/ResourceRequestCFNet.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2006, 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceRequestCFNet.h" + +#include "FormDataStreamCFNet.h" +#include "ResourceRequest.h" + +#include <CFNetwork/CFURLRequestPriv.h> + +namespace WebCore { + +CFURLRequestRef ResourceRequest::cfURLRequest() const +{ + updatePlatformRequest(); + + return m_cfRequest.get(); +} + +static inline void addHeadersFromHashMap(CFMutableURLRequestRef request, const HTTPHeaderMap& requestHeaders) +{ + if (!requestHeaders.size()) + return; + + HTTPHeaderMap::const_iterator end = requestHeaders.end(); + for (HTTPHeaderMap::const_iterator it = requestHeaders.begin(); it != end; ++it) { + CFStringRef key = it->first.createCFString(); + CFStringRef value = it->second.createCFString(); + CFURLRequestSetHTTPHeaderFieldValue(request, key, value); + CFRelease(key); + CFRelease(value); + } +} + +void ResourceRequest::doUpdatePlatformRequest() +{ + CFMutableURLRequestRef cfRequest; + + RetainPtr<CFURLRef> url(AdoptCF, ResourceRequest::url().createCFURL()); + RetainPtr<CFURLRef> mainDocumentURL(AdoptCF, ResourceRequest::mainDocumentURL().createCFURL()); + if (m_cfRequest) { + cfRequest = CFURLRequestCreateMutableCopy(0, m_cfRequest.get()); + CFURLRequestSetURL(cfRequest, url.get()); + CFURLRequestSetMainDocumentURL(cfRequest, mainDocumentURL.get()); + } else { + cfRequest = CFURLRequestCreateMutable(0, url.get(), (CFURLRequestCachePolicy)cachePolicy(), timeoutInterval(), mainDocumentURL.get()); + } + + RetainPtr<CFStringRef> requestMethod(AdoptCF, httpMethod().createCFString()); + CFURLRequestSetHTTPRequestMethod(cfRequest, requestMethod.get()); + + addHeadersFromHashMap(cfRequest, httpHeaderFields()); + WebCore::setHTTPBody(cfRequest, httpBody()); + CFURLRequestSetShouldHandleHTTPCookies(cfRequest, allowHTTPCookies()); + + if (m_cfRequest) { + RetainPtr<CFHTTPCookieStorageRef> cookieStorage(AdoptCF, CFURLRequestCopyHTTPCookieStorage(m_cfRequest.get())); + if (cookieStorage) + CFURLRequestSetHTTPCookieStorage(cfRequest, cookieStorage.get()); + CFURLRequestSetHTTPCookieStorageAcceptPolicy(cfRequest, CFURLRequestGetHTTPCookieStorageAcceptPolicy(m_cfRequest.get())); + CFURLRequestSetSSLProperties(cfRequest, CFURLRequestGetSSLProperties(m_cfRequest.get())); + } + + m_cfRequest.adoptCF(cfRequest); +} + +void ResourceRequest::doUpdateResourceRequest() +{ + m_url = CFURLRequestGetURL(m_cfRequest.get()); + + m_cachePolicy = (ResourceRequestCachePolicy)CFURLRequestGetCachePolicy(m_cfRequest.get()); + m_timeoutInterval = CFURLRequestGetTimeoutInterval(m_cfRequest.get()); + m_mainDocumentURL = CFURLRequestGetMainDocumentURL(m_cfRequest.get()); + if (CFStringRef method = CFURLRequestCopyHTTPRequestMethod(m_cfRequest.get())) { + m_httpMethod = method; + CFRelease(method); + } + m_allowHTTPCookies = CFURLRequestShouldHandleHTTPCookies(m_cfRequest.get()); + + if (CFDictionaryRef headers = CFURLRequestCopyAllHTTPHeaderFields(m_cfRequest.get())) { + CFIndex headerCount = CFDictionaryGetCount(headers); + Vector<const void*, 128> keys(headerCount); + Vector<const void*, 128> values(headerCount); + CFDictionaryGetKeysAndValues(headers, keys.data(), values.data()); + for (int i = 0; i < headerCount; ++i) + m_httpHeaderFields.set((CFStringRef)keys[i], (CFStringRef)values[i]); + CFRelease(headers); + } + + m_httpBody = httpBodyFromRequest(m_cfRequest.get()); +} + +} diff --git a/WebCore/platform/network/cf/ResourceRequestCFNet.h b/WebCore/platform/network/cf/ResourceRequestCFNet.h new file mode 100644 index 0000000..e9ebe76 --- /dev/null +++ b/WebCore/platform/network/cf/ResourceRequestCFNet.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequestCFNet_h +#define ResourceRequestCFNet_h + +typedef const struct _CFURLRequest* CFURLRequestRef; + +namespace WebCore { + + class ResourceRequest; + + void getResourceRequest(ResourceRequest&, CFURLRequestRef); + CFURLRequestRef cfURLRequest(const ResourceRequest&); +} + +#endif // ResourceRequestCFNet_h diff --git a/WebCore/platform/network/cf/ResourceResponse.h b/WebCore/platform/network/cf/ResourceResponse.h new file mode 100644 index 0000000..e14c79e --- /dev/null +++ b/WebCore/platform/network/cf/ResourceResponse.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponse_h +#define ResourceResponse_h + +#include "ResourceResponseBase.h" +#include <wtf/RetainPtr.h> + +typedef struct _CFURLResponse* CFURLResponseRef; + +namespace WebCore { + +class ResourceResponse : public ResourceResponseBase { +public: + ResourceResponse() + : m_isUpToDate(true) + { + } + + ResourceResponse(CFURLResponseRef cfResponse) + : m_cfResponse(cfResponse) + , m_isUpToDate(false) + { + m_isNull = !cfResponse; + } + + ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename) + : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename) + , m_isUpToDate(true) + { + } + + CFURLResponseRef cfURLResponse() const; + +private: + friend class ResourceResponseBase; + + void platformLazyInit(); + static bool platformCompare(const ResourceResponse& a, const ResourceResponse& b); + + RetainPtr<CFURLResponseRef> m_cfResponse; + bool m_isUpToDate; +}; + +} // namespace WebCore + +#endif // ResourceResponse_h diff --git a/WebCore/platform/network/cf/ResourceResponseCFNet.cpp b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp new file mode 100644 index 0000000..79efe89 --- /dev/null +++ b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2006, 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceResponseCFNet.h" + +#include "HTTPParsers.h" +#include "MIMETypeRegistry.h" +#include "ResourceResponse.h" +#include <CFNetwork/CFURLResponsePriv.h> +#include <wtf/RetainPtr.h> + +using namespace std; + +// We would like a better value for a maximum time_t, +// but there is no way to do that in C with any certainty. +// INT_MAX should work well enough for our purposes. +#define MAX_TIME_T ((time_t)INT_MAX) + +namespace WebCore { + +CFURLResponseRef ResourceResponse::cfURLResponse() const +{ + return m_cfResponse.get(); +} + +static inline bool filenameHasSaneExtension(const String& filename) +{ + int dot = filename.find('.'); + + // The dot can't be the first or last character in the filename. + int length = filename.length(); + return dot > 0 && dot < length - 1; +} + +static time_t toTimeT(CFAbsoluteTime time) +{ + static const double maxTimeAsDouble = std::numeric_limits<time_t>::max(); + static const double minTimeAsDouble = std::numeric_limits<time_t>::min(); + return min(max(minTimeAsDouble, time + kCFAbsoluteTimeIntervalSince1970), maxTimeAsDouble); +} + +void ResourceResponse::platformLazyInit() +{ + if (m_isUpToDate) + return; + m_isUpToDate = true; + + if (m_isNull) { + ASSERT(!m_cfResponse.get()); + return; + } + + // FIXME: We may need to do MIME type sniffing here (unless that is done in CFURLResponseGetMIMEType). + + m_url = CFURLResponseGetURL(m_cfResponse.get()); + m_mimeType = CFURLResponseGetMIMEType(m_cfResponse.get()); + m_expectedContentLength = CFURLResponseGetExpectedContentLength(m_cfResponse.get()); + m_textEncodingName = CFURLResponseGetTextEncodingName(m_cfResponse.get()); + + m_expirationDate = toTimeT(CFURLResponseGetExpirationTime(m_cfResponse.get())); + m_lastModifiedDate = toTimeT(CFURLResponseGetLastModifiedDate(m_cfResponse.get())); + + RetainPtr<CFStringRef> suggestedFilename(AdoptCF, CFURLResponseCopySuggestedFilename(m_cfResponse.get())); + m_suggestedFilename = suggestedFilename.get(); + + CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(m_cfResponse.get()); + if (httpResponse) { + m_httpStatusCode = CFHTTPMessageGetResponseStatusCode(httpResponse); + + RetainPtr<CFStringRef> statusLine(AdoptCF, CFHTTPMessageCopyResponseStatusLine(httpResponse)); + String statusText(statusLine.get()); + int spacePos = statusText.find(" "); + if (spacePos != -1) + statusText = statusText.substring(spacePos + 1); + m_httpStatusText = statusText; + + RetainPtr<CFDictionaryRef> headers(AdoptCF, CFHTTPMessageCopyAllHeaderFields(httpResponse)); + CFIndex headerCount = CFDictionaryGetCount(headers.get()); + Vector<const void*, 128> keys(headerCount); + Vector<const void*, 128> values(headerCount); + CFDictionaryGetKeysAndValues(headers.get(), keys.data(), values.data()); + for (int i = 0; i < headerCount; ++i) + m_httpHeaderFields.set((CFStringRef)keys[i], (CFStringRef)values[i]); + } else + m_httpStatusCode = 0; +} + +bool ResourceResponse::platformCompare(const ResourceResponse& a, const ResourceResponse& b) +{ + return CFEqual(a.cfURLResponse(), b.cfURLResponse()); +} + + +} diff --git a/WebCore/platform/network/cf/ResourceResponseCFNet.h b/WebCore/platform/network/cf/ResourceResponseCFNet.h new file mode 100644 index 0000000..27144c6 --- /dev/null +++ b/WebCore/platform/network/cf/ResourceResponseCFNet.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponseCFNet_h +#define ResourceResponseCFNet_h + +typedef struct _CFURLResponse* CFURLResponseRef; + +namespace WebCore { + + class ResourceResponse; + + void getResourceResponse(ResourceResponse& response, CFURLResponseRef cfResponse); + +} + +#endif // ResourceResponseCFNet_h diff --git a/WebCore/platform/network/curl/AuthenticationChallenge.h b/WebCore/platform/network/curl/AuthenticationChallenge.h new file mode 100644 index 0000000..a64d575 --- /dev/null +++ b/WebCore/platform/network/curl/AuthenticationChallenge.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" +#include "ResourceHandle.h" +#include <wtf/RefPtr.h> + +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) + : AuthenticationChallengeBase(protectionSpace, proposedCredential, previousFailureCount, response, error) + { + } + + ResourceHandle* sourceHandle() const { return m_sourceHandle.get(); } + + RefPtr<ResourceHandle> m_sourceHandle; +}; + +} + +#endif diff --git a/WebCore/platform/network/curl/CookieJarCurl.cpp b/WebCore/platform/network/curl/CookieJarCurl.cpp new file mode 100644 index 0000000..2f76ebc --- /dev/null +++ b/WebCore/platform/network/curl/CookieJarCurl.cpp @@ -0,0 +1,45 @@ +/* + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "CookieJar.h" + +#include "KURL.h" +#include "PlatformString.h" +#include "StringHash.h" + +#include <wtf/HashMap.h> + +namespace WebCore { + +static HashMap<String, String> cookieJar; + +void setCookies(Document* /*document*/, const KURL& url, const KURL& /*policyURL*/, const String& value) +{ + cookieJar.set(url.string(), value); +} + +String cookies(const Document* /*document*/, const KURL& url) +{ + return cookieJar.get(url.string()); +} + +bool cookiesEnabled(const Document* /*document*/) +{ + return true; +} + +} diff --git a/WebCore/platform/network/curl/DNSCurl.cpp b/WebCore/platform/network/curl/DNSCurl.cpp new file mode 100644 index 0000000..1ffe1a0 --- /dev/null +++ b/WebCore/platform/network/curl/DNSCurl.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 Apple Computer, 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 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 COMPUTER, INC. OR + * 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 "DNS.h" + +#include "NotImplemented.h" + +namespace WebCore { + +void prefetchDNS(const String& hostname) +{ + notImplemented(); +} + +} diff --git a/WebCore/platform/network/curl/FormDataStreamCurl.cpp b/WebCore/platform/network/curl/FormDataStreamCurl.cpp new file mode 100644 index 0000000..639a741 --- /dev/null +++ b/WebCore/platform/network/curl/FormDataStreamCurl.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2008 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk> + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 Collabora Ltd. + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "FormDataStreamCurl.h" + +#include "CString.h" +#include "FormData.h" +#include "ResourceRequest.h" + +namespace WebCore { + +FormDataStream::~FormDataStream() +{ + if (m_file) + fclose(m_file); +} + +size_t FormDataStream::read(void* ptr, size_t blockSize, size_t numberOfBlocks) +{ + // Check for overflow. + if (!numberOfBlocks || blockSize > std::numeric_limits<size_t>::max() / numberOfBlocks) + return 0; + + Vector<FormDataElement> elements; + if (m_resourceHandle->request().httpBody()) + elements = m_resourceHandle->request().httpBody()->elements(); + + if (m_formDataElementIndex >= elements.size()) + return 0; + + FormDataElement element = elements[m_formDataElementIndex]; + + size_t toSend = blockSize * numberOfBlocks; + size_t sent; + + if (element.m_type == FormDataElement::encodedFile) { + if (!m_file) + m_file = fopen(element.m_filename.utf8().data(), "rb"); + + if (!m_file) { + // FIXME: show a user error? +#ifndef NDEBUG + printf("Failed while trying to open %s for upload\n", element.m_filename.utf8().data()); +#endif + return 0; + } + + sent = fread(ptr, blockSize, numberOfBlocks, m_file); + if (!blockSize && ferror(m_file)) { + // FIXME: show a user error? +#ifndef NDEBUG + printf("Failed while trying to read %s for upload\n", element.m_filename.utf8().data()); +#endif + return 0; + } + if (feof(m_file)) { + fclose(m_file); + m_file = 0; + m_formDataElementIndex++; + } + } else { + size_t elementSize = element.m_data.size() - m_formDataElementDataOffset; + sent = elementSize > toSend ? toSend : elementSize; + memcpy(ptr, element.m_data.data() + m_formDataElementDataOffset, sent); + if (elementSize > sent) + m_formDataElementDataOffset += sent; + else { + m_formDataElementDataOffset = 0; + m_formDataElementIndex++; + } + } + + return sent; +} + +bool FormDataStream::hasMoreElements() const +{ + Vector<FormDataElement> elements; + if (m_resourceHandle->request().httpBody()) + elements = m_resourceHandle->request().httpBody()->elements(); + + return m_formDataElementIndex < elements.size(); +} + +} // namespace WebCore diff --git a/WebCore/platform/network/curl/FormDataStreamCurl.h b/WebCore/platform/network/curl/FormDataStreamCurl.h new file mode 100644 index 0000000..85ca8b0 --- /dev/null +++ b/WebCore/platform/network/curl/FormDataStreamCurl.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 FormatDataStreamCurl_h +#define FormatDataStreamCurl_h + +#include "config.h" + +#include "FileSystem.h" +#include "ResourceHandle.h" +#include <stdio.h> + +namespace WebCore { + +class FormDataStream { +public: + FormDataStream(ResourceHandle* handle) + : m_resourceHandle(handle) + , m_file(0) + , m_formDataElementIndex(0) + , m_formDataElementDataOffset(0) + { + } + + ~FormDataStream(); + + size_t read(void* ptr, size_t blockSize, size_t numberOfBlocks); + bool hasMoreElements() const; + +private: + // We can hold a weak reference to our ResourceHandle as it holds a strong reference + // to us through its ResourceHandleInternal. + ResourceHandle* m_resourceHandle; + + FILE* m_file; + size_t m_formDataElementIndex; + size_t m_formDataElementDataOffset; +}; + +} // namespace WebCore + +#endif // FormDataStreamCurl_h diff --git a/WebCore/platform/network/curl/ResourceError.h b/WebCore/platform/network/curl/ResourceError.h new file mode 100644 index 0000000..ca8d36b --- /dev/null +++ b/WebCore/platform/network/curl/ResourceError.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceError_h +#define ResourceError_h + +#include "ResourceErrorBase.h" + +namespace WebCore { + +class ResourceError : public ResourceErrorBase +{ +public: + ResourceError() + { + } + + ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) + { + } +}; + +} + +#endif // ResourceError_h_ diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp new file mode 100644 index 0000000..bbc31d4 --- /dev/null +++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2005, 2006 Michael Emmel mike.emmel@gmail.com + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceHandle.h" + +#include "DocLoader.h" +#include "NotImplemented.h" +#include "ResourceHandleInternal.h" +#include "ResourceHandleManager.h" + +#if PLATFORM(WIN) && PLATFORM(CF) +#include <wtf/RetainPtr.h> +#endif + +namespace WebCore { + +class WebCoreSynchronousLoader : public ResourceHandleClient { +public: + WebCoreSynchronousLoader(); + + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); + virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived); + virtual void didFinishLoading(ResourceHandle*); + virtual void didFail(ResourceHandle*, const ResourceError&); + + ResourceResponse resourceResponse() const { return m_response; } + ResourceError resourceError() const { return m_error; } + Vector<char> data() const { return m_data; } + +private: + ResourceResponse m_response; + ResourceError m_error; + Vector<char> m_data; +}; + +WebCoreSynchronousLoader::WebCoreSynchronousLoader() +{ +} + +void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) +{ + m_response = response; +} + +void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int) +{ + m_data.append(data, length); +} + +void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*) +{ +} + +void WebCoreSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error) +{ + m_error = error; +} + + +static HashSet<String>& allowsAnyHTTPSCertificateHosts() +{ + static HashSet<String> hosts; + + return hosts; +} + +ResourceHandleInternal::~ResourceHandleInternal() +{ + free(m_url); + if (m_customHeaders) + curl_slist_free_all(m_customHeaders); +} + +ResourceHandle::~ResourceHandle() +{ + cancel(); +} + +bool ResourceHandle::start(Frame* frame) +{ + ASSERT(frame); + ref(); + ResourceHandleManager::sharedInstance()->add(this); + return true; +} + +void ResourceHandle::cancel() +{ + ResourceHandleManager::sharedInstance()->cancel(this); +} + +PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() +{ + return 0; +} + +bool ResourceHandle::supportsBufferedData() +{ + return false; +} + +#if PLATFORM(WIN) && PLATFORM(CF) +void ResourceHandle::setHostAllowsAnyHTTPSCertificate(const String& host) +{ + allowsAnyHTTPSCertificateHosts().add(host.lower()); +} +#endif + +#if PLATFORM(WIN) && PLATFORM(CF) +// FIXME: The CFDataRef will need to be something else when +// building without +static HashMap<String, RetainPtr<CFDataRef> >& clientCerts() +{ + static HashMap<String, RetainPtr<CFDataRef> > certs; + return certs; +} + +void ResourceHandle::setClientCertificate(const String& host, CFDataRef cert) +{ + clientCerts().set(host.lower(), cert); +} +#endif + +void ResourceHandle::setDefersLoading(bool defers) +{ + if (d->m_defersLoading == defers) + return; + +#if LIBCURL_VERSION_NUM > 0x071200 + if (!d->m_handle) + d->m_defersLoading = defers; + else if (defers) { + CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL); + // If we could not defer the handle, so don't do it. + if (error != CURLE_OK) + return; + + d->m_defersLoading = defers; + } else { + // We need to set defersLoading before restarting a connection + // or libcURL will call the callbacks in curl_easy_pause and + // we would ASSERT. + d->m_defersLoading = defers; + + CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_CONT); + if (error != CURLE_OK) + // Restarting the handle has failed so just cancel it. + cancel(); + } +#else + d->m_defersLoading = defers; +#ifndef NDEBUG + printf("Deferred loading is implemented if libcURL version is above 7.18.0"); +#endif +#endif +} + +bool ResourceHandle::willLoadFromCache(ResourceRequest&) +{ + notImplemented(); + return false; +} + +bool ResourceHandle::loadsBlocked() +{ + notImplemented(); + return false; +} + +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*) +{ + WebCoreSynchronousLoader syncLoader; + ResourceHandle handle(request, &syncLoader, true, false, true); + + ResourceHandleManager* manager = ResourceHandleManager::sharedInstance(); + + manager->dispatchSynchronousJob(&handle); + + error = syncLoader.resourceError(); + data = syncLoader.data(); + response = syncLoader.resourceResponse(); +} + +//stubs needed for windows version +void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge&) +{ + notImplemented(); +} + +void ResourceHandle::receivedCredential(const AuthenticationChallenge&, const Credential&) +{ + notImplemented(); +} + +void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) +{ + notImplemented(); +} + +void ResourceHandle::receivedCancellation(const AuthenticationChallenge&) +{ + notImplemented(); +} + +} // namespace WebCore diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp new file mode 100644 index 0000000..b022913 --- /dev/null +++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp @@ -0,0 +1,700 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * Copyright (C) 2007 Alp Toker <alp@atoker.com> + * Copyright (C) 2007 Holger Hans Peter Freyther + * Copyright (C) 2008 Collabora Ltd. + * Copyright (C) 2008 Nuanti Ltd. + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceHandleManager.h" + +#include "Base64.h" +#include "CString.h" +#include "HTTPParsers.h" +#include "MIMETypeRegistry.h" +#include "NotImplemented.h" +#include "ResourceError.h" +#include "ResourceHandle.h" +#include "ResourceHandleInternal.h" +#include "TextEncoding.h" + +#include <errno.h> +#include <wtf/Vector.h> + +#if PLATFORM(GTK) + #if GLIB_CHECK_VERSION(2,12,0) + #define USE_GLIB_BASE64 + #endif +#endif + +namespace WebCore { + +const int selectTimeoutMS = 5; +const double pollTimeSeconds = 0.05; +const int maxRunningJobs = 5; + +static const bool ignoreSSLErrors = getenv("WEBKIT_IGNORE_SSL_ERRORS"); + +ResourceHandleManager::ResourceHandleManager() + : m_downloadTimer(this, &ResourceHandleManager::downloadTimerCallback) + , m_cookieJarFileName(0) + , m_runningJobs(0) +{ + curl_global_init(CURL_GLOBAL_ALL); + m_curlMultiHandle = curl_multi_init(); + m_curlShareHandle = curl_share_init(); + curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE); + curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS); +} + +ResourceHandleManager::~ResourceHandleManager() +{ + curl_multi_cleanup(m_curlMultiHandle); + curl_share_cleanup(m_curlShareHandle); + if (m_cookieJarFileName) + free(m_cookieJarFileName); + curl_global_cleanup(); +} + +void ResourceHandleManager::setCookieJarFileName(const char* cookieJarFileName) +{ + m_cookieJarFileName = strdup(cookieJarFileName); +} + +ResourceHandleManager* ResourceHandleManager::sharedInstance() +{ + static ResourceHandleManager* sharedInstance = 0; + if (!sharedInstance) + sharedInstance = new ResourceHandleManager(); + return sharedInstance; +} + +// called with data after all headers have been processed via headerCallback +static size_t writeCallback(void* ptr, size_t size, size_t nmemb, void* data) +{ + ResourceHandle* job = static_cast<ResourceHandle*>(data); + ResourceHandleInternal* d = job->getInternal(); + if (d->m_cancelled) + return 0; + +#if LIBCURL_VERSION_NUM > 0x071200 + // We should never be called when deferred loading is activated. + ASSERT(!d->m_defersLoading); +#endif + + size_t totalSize = size * nmemb; + + // this shouldn't be necessary but apparently is. CURL writes the data + // of html page even if it is a redirect that was handled internally + // can be observed e.g. on gmail.com + CURL* h = d->m_handle; + long httpCode = 0; + CURLcode err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode); + if (CURLE_OK == err && httpCode >= 300 && httpCode < 400) + return totalSize; + + // since the code in headerCallback will not have run for local files + // the code to set the URL and fire didReceiveResponse is never run, + // which means the ResourceLoader's response does not contain the URL. + // Run the code here for local files to resolve the issue. + // TODO: See if there is a better approach for handling this. + if (!d->m_response.responseFired()) { + const char* hdr; + err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr); + d->m_response.setUrl(KURL(hdr)); + if (d->client()) + d->client()->didReceiveResponse(job, d->m_response); + d->m_response.setResponseFired(true); + } + + if (d->client()) + d->client()->didReceiveData(job, static_cast<char*>(ptr), totalSize, 0); + return totalSize; +} + +/* + * This is being called for each HTTP header in the response. This includes '\r\n' + * for the last line of the header. + * + * We will add each HTTP Header to the ResourceResponse and on the termination + * of the header (\r\n) we will parse Content-Type and Content-Disposition and + * update the ResourceResponse and then send it away. + * + */ +static size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* data) +{ + ResourceHandle* job = static_cast<ResourceHandle*>(data); + ResourceHandleInternal* d = job->getInternal(); + if (d->m_cancelled) + return 0; + +#if LIBCURL_VERSION_NUM > 0x071200 + // We should never be called when deferred loading is activated. + ASSERT(!d->m_defersLoading); +#endif + + size_t totalSize = size * nmemb; + ResourceHandleClient* client = d->client(); + + String header(static_cast<const char*>(ptr), totalSize); + + /* + * a) We can finish and send the ResourceResponse + * b) We will add the current header to the HTTPHeaderMap of the ResourceResponse + * + * The HTTP standard requires to use \r\n but for compatibility it recommends to + * accept also \n. + */ + if (header == String("\r\n") || header == String("\n")) { + CURL* h = d->m_handle; + CURLcode err; + + double contentLength = 0; + err = curl_easy_getinfo(h, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength); + d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength)); + + const char* hdr; + err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr); + d->m_response.setUrl(KURL(hdr)); + + long httpCode = 0; + err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode); + d->m_response.setHTTPStatusCode(httpCode); + + d->m_response.setMimeType(extractMIMETypeFromMediaType(d->m_response.httpHeaderField("Content-Type"))); + d->m_response.setTextEncodingName(extractCharsetFromMediaType(d->m_response.httpHeaderField("Content-Type"))); + d->m_response.setSuggestedFilename(filenameFromHTTPContentDisposition(d->m_response.httpHeaderField("Content-Disposition"))); + + // HTTP redirection + if (httpCode >= 300 && httpCode < 400) { + String location = d->m_response.httpHeaderField("location"); + if (!location.isEmpty()) { + KURL newURL = KURL(job->request().url(), location); + + ResourceRequest redirectedRequest = job->request(); + redirectedRequest.setURL(newURL); + if (client) + client->willSendRequest(job, redirectedRequest, d->m_response); + + d->m_request.setURL(newURL); + + return totalSize; + } + } + + if (client) + client->didReceiveResponse(job, d->m_response); + d->m_response.setResponseFired(true); + + } else { + int splitPos = header.find(":"); + if (splitPos != -1) + d->m_response.setHTTPHeaderField(header.left(splitPos), header.substring(splitPos+1).stripWhiteSpace()); + } + + return totalSize; +} + +/* This is called to obtain HTTP POST or PUT data. + Iterate through FormData elements and upload files. + Carefully respect the given buffer size and fill the rest of the data at the next calls. +*/ +size_t readCallback(void* ptr, size_t size, size_t nmemb, void* data) +{ + ResourceHandle* job = static_cast<ResourceHandle*>(data); + ResourceHandleInternal* d = job->getInternal(); + if (d->m_cancelled) + return 0; + +#if LIBCURL_VERSION_NUM > 0x071200 + // We should never be called when deferred loading is activated. + ASSERT(!d->m_defersLoading); +#endif + + if (!size || !nmemb) + return 0; + + if (!d->m_formDataStream.hasMoreElements()) + return 0; + + size_t sent = d->m_formDataStream.read(ptr, size, nmemb); + + // Something went wrong so cancel the job. + if (!sent) + job->cancel(); + + return sent; +} + +void ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>* timer) +{ + startScheduledJobs(); + + fd_set fdread; + fd_set fdwrite; + fd_set fdexcep; + int maxfd = 0; + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = selectTimeoutMS * 1000; // select waits microseconds + + // Temporarily disable timers since signals may interrupt select(), raising EINTR errors on some platforms + setDeferringTimers(true); + int rc = 0; + do { + FD_ZERO(&fdread); + FD_ZERO(&fdwrite); + FD_ZERO(&fdexcep); + curl_multi_fdset(m_curlMultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd); + // When the 3 file descriptors are empty, winsock will return -1 + // and bail out, stopping the file download. So make sure we + // have valid file descriptors before calling select. + if (maxfd >= 0) + rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout); + } while (rc == -1 && errno == EINTR); + setDeferringTimers(false); + + if (-1 == rc) { +#ifndef NDEBUG + perror("bad: select() returned -1: "); +#endif + return; + } + + int runningHandles = 0; + while (curl_multi_perform(m_curlMultiHandle, &runningHandles) == CURLM_CALL_MULTI_PERFORM) { } + + // check the curl messages indicating completed transfers + // and free their resources + while (true) { + int messagesInQueue; + CURLMsg* msg = curl_multi_info_read(m_curlMultiHandle, &messagesInQueue); + if (!msg) + break; + + // find the node which has same d->m_handle as completed transfer + CURL* handle = msg->easy_handle; + ASSERT(handle); + ResourceHandle* job = 0; + CURLcode err = curl_easy_getinfo(handle, CURLINFO_PRIVATE, &job); + ASSERT(CURLE_OK == err); + ASSERT(job); + if (!job) + continue; + ResourceHandleInternal* d = job->getInternal(); + ASSERT(d->m_handle == handle); + + if (d->m_cancelled) { + removeFromCurl(job); + continue; + } + + if (CURLMSG_DONE != msg->msg) + continue; + + if (CURLE_OK == msg->data.result) { + if (d->client()) + d->client()->didFinishLoading(job); + } else { +#ifndef NDEBUG + char* url = 0; + curl_easy_getinfo(d->m_handle, CURLINFO_EFFECTIVE_URL, &url); + printf("Curl ERROR for url='%s', error: '%s'\n", url, curl_easy_strerror(msg->data.result)); +#endif + if (d->client()) + d->client()->didFail(job, ResourceError()); + } + + removeFromCurl(job); + } + + bool started = startScheduledJobs(); // new jobs might have been added in the meantime + + if (!m_downloadTimer.isActive() && (started || (runningHandles > 0))) + m_downloadTimer.startOneShot(pollTimeSeconds); +} + +void ResourceHandleManager::removeFromCurl(ResourceHandle* job) +{ + ResourceHandleInternal* d = job->getInternal(); + ASSERT(d->m_handle); + if (!d->m_handle) + return; + m_runningJobs--; + curl_multi_remove_handle(m_curlMultiHandle, d->m_handle); + curl_easy_cleanup(d->m_handle); + d->m_handle = 0; +} + +void ResourceHandleManager::setupPUT(ResourceHandle*, struct curl_slist**) +{ + notImplemented(); +} + +/* Calculate the length of the POST. + Force chunked data transfer if size of files can't be obtained. + */ +void ResourceHandleManager::setupPOST(ResourceHandle* job, struct curl_slist** headers) +{ + ResourceHandleInternal* d = job->getInternal(); + Vector<FormDataElement> elements; + // Fix crash when httpBody is null (see bug #16906). + if (job->request().httpBody()) + elements = job->request().httpBody()->elements(); + size_t numElements = elements.size(); + + if (!numElements) + return; + + // Do not stream for simple POST data + if (numElements == 1) { + job->request().httpBody()->flatten(d->m_postBytes); + if (d->m_postBytes.size() != 0) { + curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE); + curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, d->m_postBytes.size()); + curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDS, d->m_postBytes.data()); + } + return; + } + + // Obtain the total size of the POST + // The size of a curl_off_t could be different in WebKit and in cURL depending on + // compilation flags of both. For CURLOPT_POSTFIELDSIZE_LARGE we have to pass the + // right size or random data will be used as the size. + static int expectedSizeOfCurlOffT = 0; + if (!expectedSizeOfCurlOffT) { + curl_version_info_data *infoData = curl_version_info(CURLVERSION_NOW); + if (infoData->features & CURL_VERSION_LARGEFILE) + expectedSizeOfCurlOffT = sizeof(long long); + else + expectedSizeOfCurlOffT = sizeof(int); + } + +#if COMPILER(MSVC) + // work around compiler error in Visual Studio 2005. It can't properly + // handle math with 64-bit constant declarations. +#pragma warning(disable: 4307) +#endif + static const long long maxCurlOffT = (1LL << (expectedSizeOfCurlOffT * 8 - 1)) - 1; + curl_off_t size = 0; + bool chunkedTransfer = false; + for (size_t i = 0; i < numElements; i++) { + FormDataElement element = elements[i]; + if (element.m_type == FormDataElement::encodedFile) { + long long fileSizeResult; + if (getFileSize(element.m_filename, fileSizeResult)) { + if (fileSizeResult > maxCurlOffT) { + // File size is too big for specifying it to cURL + chunkedTransfer = true; + break; + } + size += fileSizeResult; + } else { + chunkedTransfer = true; + break; + } + } else + size += elements[i].m_data.size(); + } + + curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE); + + // cURL guesses that we want chunked encoding as long as we specify the header + if (chunkedTransfer) + *headers = curl_slist_append(*headers, "Transfer-Encoding: chunked"); + else { + if (sizeof(long long) == expectedSizeOfCurlOffT) + curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE_LARGE, (long long)size); + else + curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE_LARGE, (int)size); + } + + curl_easy_setopt(d->m_handle, CURLOPT_READFUNCTION, readCallback); + curl_easy_setopt(d->m_handle, CURLOPT_READDATA, job); +} + +void ResourceHandleManager::add(ResourceHandle* job) +{ + // we can be called from within curl, so to avoid re-entrancy issues + // schedule this job to be added the next time we enter curl download loop + m_resourceHandleList.append(job); + if (!m_downloadTimer.isActive()) + m_downloadTimer.startOneShot(pollTimeSeconds); +} + +bool ResourceHandleManager::removeScheduledJob(ResourceHandle* job) +{ + int size = m_resourceHandleList.size(); + for (int i = 0; i < size; i++) { + if (job == m_resourceHandleList[i]) { + m_resourceHandleList.remove(i); + return true; + } + } + return false; +} + +bool ResourceHandleManager::startScheduledJobs() +{ + // TODO: Create a separate stack of jobs for each domain. + + bool started = false; + while (!m_resourceHandleList.isEmpty() && m_runningJobs < maxRunningJobs) { + ResourceHandle* job = m_resourceHandleList[0]; + m_resourceHandleList.remove(0); + startJob(job); + started = true; + } + return started; +} + +static void parseDataUrl(ResourceHandle* handle) +{ + ResourceHandleClient* client = handle->client(); + + ASSERT(client); + if (!client) + return; + + String url = handle->request().url().string(); + ASSERT(url.startsWith("data:", false)); + + int index = url.find(','); + if (index == -1) { + client->cannotShowURL(handle); + return; + } + + String mediaType = url.substring(5, index - 5); + String data = url.substring(index + 1); + + bool base64 = mediaType.endsWith(";base64", false); + if (base64) + mediaType = mediaType.left(mediaType.length() - 7); + + if (mediaType.isEmpty()) + mediaType = "text/plain;charset=US-ASCII"; + + String mimeType = extractMIMETypeFromMediaType(mediaType); + String charset = extractCharsetFromMediaType(mediaType); + + ResourceResponse response; + response.setMimeType(mimeType); + + if (base64) { + data = decodeURLEscapeSequences(data); + response.setTextEncodingName(charset); + client->didReceiveResponse(handle, response); + + // Use the GLib Base64 if available, since WebCore's decoder isn't + // general-purpose and fails on Acid3 test 97 (whitespace). +#ifdef USE_GLIB_BASE64 + size_t outLength = 0; + char* outData = 0; + outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength)); + if (outData && outLength > 0) + client->didReceiveData(handle, outData, outLength, 0); + g_free(outData); +#else + Vector<char> out; + if (base64Decode(data.latin1().data(), data.latin1().length(), out) && out.size() > 0) + client->didReceiveData(handle, out.data(), out.size(), 0); +#endif + } else { + // We have to convert to UTF-16 early due to limitations in KURL + data = decodeURLEscapeSequences(data, TextEncoding(charset)); + response.setTextEncodingName("UTF-16"); + client->didReceiveResponse(handle, response); + if (data.length() > 0) + client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0); + } + + client->didFinishLoading(handle); +} + +void ResourceHandleManager::dispatchSynchronousJob(ResourceHandle* job) +{ + KURL kurl = job->request().url(); + + if (kurl.protocolIs("data")) { + parseDataUrl(job); + return; + } + + ResourceHandleInternal* handle = job->getInternal(); + +#if LIBCURL_VERSION_NUM > 0x071200 + // If defersLoading is true and we call curl_easy_perform + // on a paused handle, libcURL would do the transfert anyway + // and we would assert so force defersLoading to be false. + handle->m_defersLoading = false; +#endif + + initializeHandle(job); + + // curl_easy_perform blocks until the transfert is finished. + CURLcode ret = curl_easy_perform(handle->m_handle); + + if (ret != 0) { + ResourceError error(String(handle->m_url), ret, String(handle->m_url), String(curl_easy_strerror(ret))); + handle->client()->didFail(job, error); + } + + curl_easy_cleanup(handle->m_handle); +} + +void ResourceHandleManager::startJob(ResourceHandle* job) +{ + KURL kurl = job->request().url(); + + if (kurl.protocolIs("data")) { + parseDataUrl(job); + return; + } + + initializeHandle(job); + + m_runningJobs++; + CURLMcode ret = curl_multi_add_handle(m_curlMultiHandle, job->getInternal()->m_handle); + // don't call perform, because events must be async + // timeout will occur and do curl_multi_perform + if (ret && ret != CURLM_CALL_MULTI_PERFORM) { +#ifndef NDEBUG + printf("Error %d starting job %s\n", ret, encodeWithURLEscapeSequences(job->request().url().string()).latin1().data()); +#endif + job->cancel(); + return; + } +} + +void ResourceHandleManager::initializeHandle(ResourceHandle* job) +{ + KURL kurl = job->request().url(); + + // Remove any fragment part, otherwise curl will send it as part of the request. + kurl.removeRef(); + + ResourceHandleInternal* d = job->getInternal(); + String url = kurl.string(); + + if (kurl.isLocalFile()) { + String query = kurl.query(); + // Remove any query part sent to a local file. + if (!query.isEmpty()) + url = url.left(url.find(query)); + // Determine the MIME type based on the path. + d->m_response.setMimeType(MIMETypeRegistry::getMIMETypeForPath(url)); + } + + d->m_handle = curl_easy_init(); + +#if LIBCURL_VERSION_NUM > 0x071200 + if (d->m_defersLoading) { + CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL); + // If we did not pause the handle, we would ASSERT in the + // header callback. So just assert here. + ASSERT(error == CURLE_OK); + } +#endif +#ifndef NDEBUG + if (getenv("DEBUG_CURL")) + curl_easy_setopt(d->m_handle, CURLOPT_VERBOSE, 1); +#endif + curl_easy_setopt(d->m_handle, CURLOPT_PRIVATE, job); + curl_easy_setopt(d->m_handle, CURLOPT_ERRORBUFFER, m_curlErrorBuffer); + curl_easy_setopt(d->m_handle, CURLOPT_WRITEFUNCTION, writeCallback); + curl_easy_setopt(d->m_handle, CURLOPT_WRITEDATA, job); + curl_easy_setopt(d->m_handle, CURLOPT_HEADERFUNCTION, headerCallback); + curl_easy_setopt(d->m_handle, CURLOPT_WRITEHEADER, job); + curl_easy_setopt(d->m_handle, CURLOPT_AUTOREFERER, 1); + curl_easy_setopt(d->m_handle, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(d->m_handle, CURLOPT_MAXREDIRS, 10); + curl_easy_setopt(d->m_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY); + curl_easy_setopt(d->m_handle, CURLOPT_SHARE, m_curlShareHandle); + curl_easy_setopt(d->m_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5); // 5 minutes + // FIXME: Enable SSL verification when we have a way of shipping certs + // and/or reporting SSL errors to the user. + if (ignoreSSLErrors) + curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, false); + // enable gzip and deflate through Accept-Encoding: + curl_easy_setopt(d->m_handle, CURLOPT_ENCODING, ""); + + // url must remain valid through the request + ASSERT(!d->m_url); + + // url is in ASCII so latin1() will only convert it to char* without character translation. + d->m_url = strdup(url.latin1().data()); + curl_easy_setopt(d->m_handle, CURLOPT_URL, d->m_url); + + if (m_cookieJarFileName) { + curl_easy_setopt(d->m_handle, CURLOPT_COOKIEFILE, m_cookieJarFileName); + curl_easy_setopt(d->m_handle, CURLOPT_COOKIEJAR, m_cookieJarFileName); + } + + struct curl_slist* headers = 0; + if (job->request().httpHeaderFields().size() > 0) { + HTTPHeaderMap customHeaders = job->request().httpHeaderFields(); + HTTPHeaderMap::const_iterator end = customHeaders.end(); + for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) { + String key = it->first; + String value = it->second; + String headerString(key); + headerString.append(": "); + headerString.append(value); + CString headerLatin1 = headerString.latin1(); + headers = curl_slist_append(headers, headerLatin1.data()); + } + } + + if ("GET" == job->request().httpMethod()) + curl_easy_setopt(d->m_handle, CURLOPT_HTTPGET, TRUE); + else if ("POST" == job->request().httpMethod()) + setupPOST(job, &headers); + else if ("PUT" == job->request().httpMethod()) + setupPUT(job, &headers); + else if ("HEAD" == job->request().httpMethod()) + curl_easy_setopt(d->m_handle, CURLOPT_NOBODY, TRUE); + + if (headers) { + curl_easy_setopt(d->m_handle, CURLOPT_HTTPHEADER, headers); + d->m_customHeaders = headers; + } +} + +void ResourceHandleManager::cancel(ResourceHandle* job) +{ + if (removeScheduledJob(job)) + return; + + ResourceHandleInternal* d = job->getInternal(); + d->m_cancelled = true; + if (!m_downloadTimer.isActive()) + m_downloadTimer.startOneShot(pollTimeSeconds); +} + +} // namespace WebCore diff --git a/WebCore/platform/network/curl/ResourceHandleManager.h b/WebCore/platform/network/curl/ResourceHandleManager.h new file mode 100644 index 0000000..f3ad234 --- /dev/null +++ b/WebCore/platform/network/curl/ResourceHandleManager.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceHandleManager_h +#define ResourceHandleManager_h + +#include "Frame.h" +#include "Timer.h" +#include "ResourceHandleClient.h" + +#include <curl/curl.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class ResourceHandleManager { +public: + static ResourceHandleManager* sharedInstance(); + void add(ResourceHandle*); + void cancel(ResourceHandle*); + void setCookieJarFileName(const char* cookieJarFileName); + + void dispatchSynchronousJob(ResourceHandle*); + + void setupPOST(ResourceHandle*, struct curl_slist**); + void setupPUT(ResourceHandle*, struct curl_slist**); + +private: + ResourceHandleManager(); + ~ResourceHandleManager(); + void downloadTimerCallback(Timer<ResourceHandleManager>*); + void removeFromCurl(ResourceHandle*); + bool removeScheduledJob(ResourceHandle*); + void startJob(ResourceHandle*); + bool startScheduledJobs(); + + void initializeHandle(ResourceHandle*); + + Timer<ResourceHandleManager> m_downloadTimer; + CURLM* m_curlMultiHandle; + CURLSH* m_curlShareHandle; + char* m_cookieJarFileName; + char m_curlErrorBuffer[CURL_ERROR_SIZE]; + Vector<ResourceHandle*> m_resourceHandleList; + int m_runningJobs; +}; + +} + +#endif diff --git a/WebCore/platform/network/curl/ResourceRequest.h b/WebCore/platform/network/curl/ResourceRequest.h new file mode 100644 index 0000000..b3032aa --- /dev/null +++ b/WebCore/platform/network/curl/ResourceRequest.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequest_h +#define ResourceRequest_h + +#include "ResourceRequestBase.h" + +typedef const struct _CFURLRequest* CFURLRequestRef; + +namespace WebCore { + + struct ResourceRequest : ResourceRequestBase { + + ResourceRequest(const String& url) + : ResourceRequestBase(KURL(url), UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url) + : ResourceRequestBase(url, UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy) + : ResourceRequestBase(url, policy) + { + setHTTPReferrer(referrer); + } + + ResourceRequest() + : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + { + } + + // Needed for compatibility. + CFURLRequestRef cfURLRequest() const { return 0; } + + private: + friend class ResourceRequestBase; + + void doUpdatePlatformRequest() {} + void doUpdateResourceRequest() {} + }; + +} // namespace WebCore + +#endif // ResourceRequest_h diff --git a/WebCore/platform/network/curl/ResourceResponse.h b/WebCore/platform/network/curl/ResourceResponse.h new file mode 100644 index 0000000..6195f61 --- /dev/null +++ b/WebCore/platform/network/curl/ResourceResponse.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponse_h +#define ResourceResponse_h + +#include "ResourceResponseBase.h" + +namespace WebCore { + +class ResourceResponse : public ResourceResponseBase { +public: + ResourceResponse() + : m_responseFired(false) + { + } + + ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename) + : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename), + m_responseFired(false) + { + } + + void setResponseFired(bool fired) { m_responseFired = fired; } + bool responseFired() { return m_responseFired; } + +private: + bool m_responseFired; +}; + +} // namespace WebCore + +#endif // ResourceResponse_h diff --git a/WebCore/platform/network/mac/AuthenticationChallenge.h b/WebCore/platform/network/mac/AuthenticationChallenge.h new file mode 100644 index 0000000..e8f3a2d --- /dev/null +++ b/WebCore/platform/network/mac/AuthenticationChallenge.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" + +#include <wtf/RetainPtr.h> +#ifndef __OBJC__ +typedef struct objc_object *id; +class NSURLAuthenticationChallenge; +#else +@class NSURLAuthenticationChallenge; +#endif + +namespace WebCore { + +class AuthenticationChallenge : public AuthenticationChallengeBase { +public: + 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(); } + +private: + friend class AuthenticationChallengeBase; + static bool platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b); + + RetainPtr<id> m_sender; + RetainPtr<NSURLAuthenticationChallenge *> m_macChallenge; +}; + +} + +#endif diff --git a/WebCore/platform/network/mac/AuthenticationMac.h b/WebCore/platform/network/mac/AuthenticationMac.h new file mode 100644 index 0000000..f55ac24 --- /dev/null +++ b/WebCore/platform/network/mac/AuthenticationMac.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationMac_h +#define AuthenticationMac_h + +#ifdef __OBJC__ + +@class NSURLAuthenticationChallenge; +@class NSURLCredential; +@class NSURLProtectionSpace; + +namespace WebCore { + +class AuthenticationChallenge; +class Credential; +class ProtectionSpace; + +NSURLAuthenticationChallenge *mac(const AuthenticationChallenge&); +NSURLProtectionSpace *mac(const ProtectionSpace&); +NSURLCredential *mac(const Credential&); + +AuthenticationChallenge core(NSURLAuthenticationChallenge *); +ProtectionSpace core(NSURLProtectionSpace *); +Credential core(NSURLCredential *); + +} +#endif + +#endif diff --git a/WebCore/platform/network/mac/AuthenticationMac.mm b/WebCore/platform/network/mac/AuthenticationMac.mm new file mode 100644 index 0000000..54e7681 --- /dev/null +++ b/WebCore/platform/network/mac/AuthenticationMac.mm @@ -0,0 +1,245 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ +#import "config.h" +#import "AuthenticationMac.h" + +#import "AuthenticationChallenge.h" +#import "Credential.h" +#import "ProtectionSpace.h" + +#import <Foundation/NSURLAuthenticationChallenge.h> +#import <Foundation/NSURLCredential.h> +#import <Foundation/NSURLProtectionSpace.h> + + +namespace WebCore { + + +AuthenticationChallenge::AuthenticationChallenge(const ProtectionSpace& protectionSpace, + const Credential& proposedCredential, + unsigned previousFailureCount, + const ResourceResponse& response, + const ResourceError& error) + : AuthenticationChallengeBase(protectionSpace, + proposedCredential, + previousFailureCount, + response, + error) +{ +} + +AuthenticationChallenge::AuthenticationChallenge(NSURLAuthenticationChallenge *macChallenge) + : AuthenticationChallengeBase(core([macChallenge protectionSpace]), + core([macChallenge proposedCredential]), + [macChallenge previousFailureCount], + [macChallenge failureResponse], + [macChallenge error]) + , m_sender([macChallenge sender]) + , m_macChallenge(macChallenge) +{ +} + +bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b) +{ + if (a.sender() != b.sender()) + return false; + + if (a.nsURLAuthenticationChallenge() != b.nsURLAuthenticationChallenge()) + return false; + + return true; +} + +NSURLAuthenticationChallenge *mac(const AuthenticationChallenge& coreChallenge) +{ + if (coreChallenge.nsURLAuthenticationChallenge()) + return coreChallenge.nsURLAuthenticationChallenge(); + + return [[[NSURLAuthenticationChallenge alloc] initWithProtectionSpace:mac(coreChallenge.protectionSpace()) + proposedCredential:mac(coreChallenge.proposedCredential()) + previousFailureCount:coreChallenge.previousFailureCount() + failureResponse:coreChallenge.failureResponse().nsURLResponse() + error:coreChallenge.error() + sender:coreChallenge.sender()] autorelease]; +} + +NSURLProtectionSpace *mac(const ProtectionSpace& coreSpace) +{ + NSString *proxyType = nil; + NSString *protocol = nil; + switch (coreSpace.serverType()) { + case ProtectionSpaceServerHTTP: + protocol = @"http"; + break; + case ProtectionSpaceServerHTTPS: + protocol = @"https"; + break; + case ProtectionSpaceServerFTP: + protocol = @"ftp"; + break; + case ProtectionSpaceServerFTPS: + protocol = @"ftps"; + break; + case ProtectionSpaceProxyHTTP: + proxyType = NSURLProtectionSpaceHTTPProxy; + break; + case ProtectionSpaceProxyHTTPS: + proxyType = NSURLProtectionSpaceHTTPSProxy; + break; + case ProtectionSpaceProxyFTP: + proxyType = NSURLProtectionSpaceFTPProxy; + break; + case ProtectionSpaceProxySOCKS: + proxyType = NSURLProtectionSpaceSOCKSProxy; + break; + default: + ASSERT_NOT_REACHED(); + } + + NSString *method = nil; + switch (coreSpace.authenticationScheme()) { + case ProtectionSpaceAuthenticationSchemeDefault: + method = NSURLAuthenticationMethodDefault; + break; + case ProtectionSpaceAuthenticationSchemeHTTPBasic: + method = NSURLAuthenticationMethodHTTPBasic; + break; + case ProtectionSpaceAuthenticationSchemeHTTPDigest: + method = NSURLAuthenticationMethodHTTPDigest; + break; + case ProtectionSpaceAuthenticationSchemeHTMLForm: + method = NSURLAuthenticationMethodHTMLForm; + break; + default: + ASSERT_NOT_REACHED(); + } + + if (proxyType) + return [[[NSURLProtectionSpace alloc] initWithProxyHost:coreSpace.host() + port:coreSpace.port() + type:proxyType + realm:coreSpace.realm() + authenticationMethod:method] autorelease]; + return [[[NSURLProtectionSpace alloc] initWithHost:coreSpace.host() + port:coreSpace.port() + protocol:protocol + realm:coreSpace.realm() + authenticationMethod:method] autorelease]; +} + +NSURLCredential *mac(const Credential& coreCredential) +{ + NSURLCredentialPersistence persistence = NSURLCredentialPersistenceNone; + switch (coreCredential.persistence()) { + case CredentialPersistenceNone: + break; + case CredentialPersistenceForSession: + persistence = NSURLCredentialPersistenceForSession; + break; + case CredentialPersistencePermanent: + persistence = NSURLCredentialPersistencePermanent; + break; + default: + ASSERT_NOT_REACHED(); + } + + return [[[NSURLCredential alloc] initWithUser:coreCredential.user() + password:coreCredential.password() + persistence:persistence] + autorelease]; +} + +AuthenticationChallenge core(NSURLAuthenticationChallenge *macChallenge) +{ + return AuthenticationChallenge(macChallenge); +} + +ProtectionSpace core(NSURLProtectionSpace *macSpace) +{ + ProtectionSpaceServerType serverType = ProtectionSpaceProxyHTTP; + + if ([macSpace isProxy]) { + NSString *proxyType = [macSpace proxyType]; + if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPProxy]) + serverType = ProtectionSpaceProxyHTTP; + else if ([proxyType isEqualToString:NSURLProtectionSpaceHTTPSProxy]) + serverType = ProtectionSpaceProxyHTTPS; + else if ([proxyType isEqualToString:NSURLProtectionSpaceFTPProxy]) + serverType = ProtectionSpaceProxyFTP; + else if ([proxyType isEqualToString:NSURLProtectionSpaceSOCKSProxy]) + serverType = ProtectionSpaceProxySOCKS; + else + ASSERT_NOT_REACHED(); + } else { + NSString *protocol = [macSpace protocol]; + if ([protocol caseInsensitiveCompare:@"http"] == NSOrderedSame) + serverType = ProtectionSpaceServerHTTP; + else if ([protocol caseInsensitiveCompare:@"https"] == NSOrderedSame) + serverType = ProtectionSpaceServerHTTPS; + else if ([protocol caseInsensitiveCompare:@"ftp"] == NSOrderedSame) + serverType = ProtectionSpaceServerFTP; + else if ([protocol caseInsensitiveCompare:@"ftps"] == NSOrderedSame) + serverType = ProtectionSpaceServerFTPS; + else + ASSERT_NOT_REACHED(); + } + + ProtectionSpaceAuthenticationScheme scheme = ProtectionSpaceAuthenticationSchemeDefault; + NSString *method = [macSpace authenticationMethod]; + if ([method isEqualToString:NSURLAuthenticationMethodDefault]) + scheme = ProtectionSpaceAuthenticationSchemeDefault; + else if ([method isEqualToString:NSURLAuthenticationMethodHTTPBasic]) + scheme = ProtectionSpaceAuthenticationSchemeHTTPBasic; + else if ([method isEqualToString:NSURLAuthenticationMethodHTTPDigest]) + scheme = ProtectionSpaceAuthenticationSchemeHTTPDigest; + else if ([method isEqualToString:NSURLAuthenticationMethodHTMLForm]) + scheme = ProtectionSpaceAuthenticationSchemeHTMLForm; + else + ASSERT_NOT_REACHED(); + + return ProtectionSpace([macSpace host], [macSpace port], serverType, [macSpace realm], scheme); + +} + +Credential core(NSURLCredential *macCredential) +{ + CredentialPersistence persistence = CredentialPersistenceNone; + switch ([macCredential persistence]) { + case NSURLCredentialPersistenceNone: + break; + case NSURLCredentialPersistenceForSession: + persistence = CredentialPersistenceForSession; + break; + case NSURLCredentialPersistencePermanent: + persistence = CredentialPersistencePermanent; + break; + default: + ASSERT_NOT_REACHED(); + } + + return Credential([macCredential user], [macCredential password], persistence); +} + +}; diff --git a/WebCore/platform/network/mac/FormDataStreamMac.h b/WebCore/platform/network/mac/FormDataStreamMac.h new file mode 100644 index 0000000..22cc8ce --- /dev/null +++ b/WebCore/platform/network/mac/FormDataStreamMac.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2005, 2006, 2008 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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 FormDataStreamMac_h +#define FormDataStreamMac_h + +#include "FormData.h" + +@class NSMutableURLRequest; + +namespace WebCore { + + class FormData; + class ResourceHandle; + + void setHTTPBody(NSMutableURLRequest *, PassRefPtr<FormData>); + FormData* httpBodyFromStream(NSInputStream *); + + void associateStreamWithResourceHandle(NSInputStream *, ResourceHandle*); + void disassociateStreamWithResourceHandle(NSInputStream *); + +} // namespace WebCore + +#endif // FormDataStreamMac_h diff --git a/WebCore/platform/network/mac/FormDataStreamMac.mm b/WebCore/platform/network/mac/FormDataStreamMac.mm new file mode 100644 index 0000000..3ef224d --- /dev/null +++ b/WebCore/platform/network/mac/FormDataStreamMac.mm @@ -0,0 +1,390 @@ +/* + * Copyright (C) 2005, 2006, 2008 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +/* originally written by Becky Willrich, additional code by Darin Adler */ + +#import "config.h" +#import "FormDataStreamMac.h" + +#import "CString.h" +#import "FormData.h" +#import "ResourceHandle.h" +#import "ResourceHandleClient.h" +#import "SchedulePair.h" +#import "WebCoreSystemInterface.h" +#import <sys/stat.h> +#import <sys/types.h> +#import <wtf/Assertions.h> +#import <wtf/HashMap.h> +#import <wtf/MainThread.h> +#import <wtf/Threading.h> + +namespace WebCore { + +typedef HashMap<CFReadStreamRef, RefPtr<FormData> > StreamFormDataMap; +static StreamFormDataMap& getStreamFormDataMap() +{ + static StreamFormDataMap streamFormDataMap; + return streamFormDataMap; +} + +typedef HashMap<CFReadStreamRef, RefPtr<ResourceHandle> > StreamResourceHandleMap; +static StreamResourceHandleMap& getStreamResourceHandleMap() +{ + static StreamResourceHandleMap streamResourceHandleMap; + return streamResourceHandleMap; +} + +void associateStreamWithResourceHandle(NSInputStream *stream, ResourceHandle* resourceHandle) +{ + ASSERT(isMainThread()); + + ASSERT(resourceHandle); + + if (!stream) + return; + + if (!getStreamFormDataMap().contains((CFReadStreamRef)stream)) + return; + + ASSERT(!getStreamResourceHandleMap().contains((CFReadStreamRef)stream)); + getStreamResourceHandleMap().set((CFReadStreamRef)stream, resourceHandle); +} + +void disassociateStreamWithResourceHandle(NSInputStream *stream) +{ + ASSERT(isMainThread()); + + if (!stream) + return; + + getStreamResourceHandleMap().remove((CFReadStreamRef)stream); +} + +struct DidSendDataCallbackData { + DidSendDataCallbackData(CFReadStreamRef stream_, unsigned long long bytesSent_, unsigned long long streamLength_) + : stream(stream_) + , bytesSent(bytesSent_) + , streamLength(streamLength_) + { + } + + CFReadStreamRef stream; + unsigned long long bytesSent; + unsigned long long streamLength; +}; + +static void performDidSendDataCallback(void* context) +{ + ASSERT(isMainThread()); + + DidSendDataCallbackData* data = static_cast<DidSendDataCallbackData*>(context); + ResourceHandle* resourceHandle = getStreamResourceHandleMap().get(data->stream).get(); + + if (resourceHandle && resourceHandle->client()) + resourceHandle->client()->didSendData(resourceHandle, data->bytesSent, data->streamLength); + + delete data; +} + +static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context); + +struct FormContext { + FormData* formData; + unsigned long long streamLength; +}; + +struct FormStreamFields { + SchedulePairHashSet scheduledRunLoopPairs; + Vector<FormDataElement> remainingElements; // in reverse order + CFReadStreamRef currentStream; + char* currentData; + CFReadStreamRef formStream; + unsigned long long streamLength; + unsigned long long bytesSent; +}; + +static void closeCurrentStream(FormStreamFields *form) +{ + if (form->currentStream) { + CFReadStreamClose(form->currentStream); + CFReadStreamSetClient(form->currentStream, kCFStreamEventNone, NULL, NULL); + CFRelease(form->currentStream); + form->currentStream = NULL; + } + if (form->currentData) { + fastFree(form->currentData); + form->currentData = 0; + } +} + +static void advanceCurrentStream(FormStreamFields *form) +{ + closeCurrentStream(form); + + if (form->remainingElements.isEmpty()) + return; + + // Create the new stream. + FormDataElement& nextInput = form->remainingElements.last(); + if (nextInput.m_type == FormDataElement::data) { + size_t size = nextInput.m_data.size(); + char* data = nextInput.m_data.releaseBuffer(); + form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull); + form->currentData = data; + } else { + const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename; + CFStringRef filename = path.createCFString(); + CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLPOSIXPathStyle, FALSE); + CFRelease(filename); + form->currentStream = CFReadStreamCreateWithFile(0, fileURL); + CFRelease(fileURL); + } + form->remainingElements.removeLast(); + + // Set up the callback. + CFStreamClientContext context = { 0, form, NULL, NULL, NULL }; + CFReadStreamSetClient(form->currentStream, kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, + formEventCallback, &context); + + // Schedule with the current set of run loops. + SchedulePairHashSet::iterator end = form->scheduledRunLoopPairs.end(); + for (SchedulePairHashSet::iterator it = form->scheduledRunLoopPairs.begin(); it != end; ++it) + CFReadStreamScheduleWithRunLoop(form->currentStream, (*it)->runLoop(), (*it)->mode()); +} + +static void openNextStream(FormStreamFields* form) +{ + // Skip over any streams we can't open. + // For some purposes we might want to return an error, but the current NSURLConnection + // can't really do anything useful with an error at this point, so this is better. + advanceCurrentStream(form); + while (form->currentStream && !CFReadStreamOpen(form->currentStream)) + advanceCurrentStream(form); +} + +static void* formCreate(CFReadStreamRef stream, void* context) +{ + FormContext* formContext = static_cast<FormContext*>(context); + + FormStreamFields* newInfo = new FormStreamFields; + newInfo->currentStream = NULL; + newInfo->currentData = 0; + newInfo->formStream = stream; // Don't retain. That would create a reference cycle. + newInfo->streamLength = formContext->streamLength; + newInfo->bytesSent = 0; + + FormData* formData = formContext->formData; + + // Append in reverse order since we remove elements from the end. + size_t size = formData->elements().size(); + newInfo->remainingElements.reserveCapacity(size); + for (size_t i = 0; i < size; ++i) + newInfo->remainingElements.append(formData->elements()[size - i - 1]); + + getStreamFormDataMap().set(stream, adoptRef(formData)); + + return newInfo; +} + +static void formFinalize(CFReadStreamRef stream, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + getStreamFormDataMap().remove(stream); + + closeCurrentStream(form); + delete form; +} + +static Boolean formOpen(CFReadStreamRef stream, CFStreamError* error, Boolean* openComplete, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + openNextStream(form); + + *openComplete = TRUE; + error->error = 0; + return TRUE; +} + +static CFIndex formRead(CFReadStreamRef stream, UInt8* buffer, CFIndex bufferLength, CFStreamError* error, Boolean* atEOF, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + while (form->currentStream) { + CFIndex bytesRead = CFReadStreamRead(form->currentStream, buffer, bufferLength); + if (bytesRead < 0) { + *error = CFReadStreamGetError(form->currentStream); + return -1; + } + if (bytesRead > 0) { + error->error = 0; + *atEOF = FALSE; + form->bytesSent += bytesRead; + + if (!ResourceHandle::didSendBodyDataDelegateExists()) { + // FIXME: Figure out how to only do this when a ResourceHandleClient is available. + DidSendDataCallbackData* data = new DidSendDataCallbackData(stream, form->bytesSent, form->streamLength); + callOnMainThread(performDidSendDataCallback, data); + } + + return bytesRead; + } + openNextStream(form); + } + + error->error = 0; + *atEOF = TRUE; + return 0; +} + +static Boolean formCanRead(CFReadStreamRef stream, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + while (form->currentStream && CFReadStreamGetStatus(form->currentStream) == kCFStreamStatusAtEnd) { + openNextStream(form); + } + if (!form->currentStream) { + wkSignalCFReadStreamEnd(stream); + return FALSE; + } + return CFReadStreamHasBytesAvailable(form->currentStream); +} + +static void formClose(CFReadStreamRef stream, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + closeCurrentStream(form); +} + +static void formSchedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + if (form->currentStream) + CFReadStreamScheduleWithRunLoop(form->currentStream, runLoop, runLoopMode); + form->scheduledRunLoopPairs.add(SchedulePair::create(runLoop, runLoopMode)); +} + +static void formUnschedule(CFReadStreamRef stream, CFRunLoopRef runLoop, CFStringRef runLoopMode, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + if (form->currentStream) + CFReadStreamUnscheduleFromRunLoop(form->currentStream, runLoop, runLoopMode); + form->scheduledRunLoopPairs.remove(SchedulePair::create(runLoop, runLoopMode)); +} + +static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, void* context) +{ + FormStreamFields* form = static_cast<FormStreamFields*>(context); + + switch (type) { + case kCFStreamEventHasBytesAvailable: + wkSignalCFReadStreamHasBytes(form->formStream); + break; + case kCFStreamEventErrorOccurred: { + CFStreamError readStreamError = CFReadStreamGetError(stream); + wkSignalCFReadStreamError(form->formStream, &readStreamError); + break; + } + case kCFStreamEventEndEncountered: + openNextStream(form); + if (!form->currentStream) { + wkSignalCFReadStreamEnd(form->formStream); + } + break; + case kCFStreamEventNone: + LOG_ERROR("unexpected kCFStreamEventNone"); + break; + case kCFStreamEventOpenCompleted: + LOG_ERROR("unexpected kCFStreamEventOpenCompleted"); + break; + case kCFStreamEventCanAcceptBytes: + LOG_ERROR("unexpected kCFStreamEventCanAcceptBytes"); + break; + } +} + +void setHTTPBody(NSMutableURLRequest *request, PassRefPtr<FormData> formData) +{ + if (!formData) + return; + + size_t count = formData->elements().size(); + + // Handle the common special case of one piece of form data, with no files. + if (count == 1 && !formData->alwaysStream()) { + const FormDataElement& element = formData->elements()[0]; + if (element.m_type == FormDataElement::data) { + NSData *data = [[NSData alloc] initWithBytes:element.m_data.data() length:element.m_data.size()]; + [request setHTTPBody:data]; + [data release]; + return; + } + } + + // Precompute the content length so NSURLConnection doesn't use chunked mode. + long long length = 0; + for (size_t i = 0; i < count; ++i) { + const FormDataElement& element = formData->elements()[i]; + if (element.m_type == FormDataElement::data) + length += element.m_data.size(); + else { + const String& filename = element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename; + struct stat sb; + int statResult = stat(filename.utf8().data(), &sb); + if (statResult == 0 && (sb.st_mode & S_IFMT) == S_IFREG) + length += sb.st_size; + } + } + + // Set the length. + [request setValue:[NSString stringWithFormat:@"%lld", length] forHTTPHeaderField:@"Content-Length"]; + + // Create and set the stream. + + // Pass the length along with the formData so it does not have to be recomputed. + FormContext formContext = { formData.releaseRef(), length }; + + CFReadStreamRef stream = wkCreateCustomCFReadStream(formCreate, formFinalize, + formOpen, formRead, formCanRead, formClose, formSchedule, formUnschedule, + &formContext); + [request setHTTPBodyStream:(NSInputStream *)stream]; + CFRelease(stream); +} + +FormData* httpBodyFromStream(NSInputStream* stream) +{ + return getStreamFormDataMap().get((CFReadStreamRef)stream).get(); +} + +} // namespace WebCore diff --git a/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp b/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp new file mode 100644 index 0000000..6e0b70d --- /dev/null +++ b/WebCore/platform/network/mac/NetworkStateNotifierMac.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2008 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. ``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 + * 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 "NetworkStateNotifier.h" + +#include <SystemConfiguration/SystemConfiguration.h> + +namespace WebCore { + +static const double StateChangeTimerInterval = 2.0; + +void NetworkStateNotifier::updateState() +{ + // Assume that we're offline until proven otherwise. + m_isOnLine = false; + + RetainPtr<CFStringRef> str(AdoptCF, SCDynamicStoreKeyCreateNetworkInterface(0, kSCDynamicStoreDomainState)); + + RetainPtr<CFPropertyListRef> propertyList(AdoptCF, SCDynamicStoreCopyValue(m_store.get(), str.get())); + + if (!propertyList) + return; + + if (CFGetTypeID(propertyList.get()) != CFDictionaryGetTypeID()) + return; + + CFArrayRef netInterfaces = (CFArrayRef)CFDictionaryGetValue((CFDictionaryRef)propertyList.get(), kSCDynamicStorePropNetInterfaces); + if (CFGetTypeID(netInterfaces) != CFArrayGetTypeID()) + return; + + for (CFIndex i = 0; i < CFArrayGetCount(netInterfaces); i++) { + CFStringRef interface = (CFStringRef)CFArrayGetValueAtIndex(netInterfaces, i); + if (CFGetTypeID(interface) != CFStringGetTypeID()) + continue; + + // Ignore the loopback interface. + if (CFStringFind(interface, CFSTR("lo"), kCFCompareAnchored).location != kCFNotFound) + continue; + + RetainPtr<CFStringRef> key(AdoptCF, SCDynamicStoreKeyCreateNetworkInterfaceEntity(0, kSCDynamicStoreDomainState, interface, kSCEntNetIPv4)); + + RetainPtr<CFArrayRef> keyList(AdoptCF, SCDynamicStoreCopyKeyList(m_store.get(), key.get())); + + if (keyList && CFArrayGetCount(keyList.get())) { + m_isOnLine = true; + break; + } + } +} + +void NetworkStateNotifier::dynamicStoreCallback(SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) +{ + NetworkStateNotifier* notifier = static_cast<NetworkStateNotifier*>(info); + + // Calling updateState() could be expensive so we schedule a timer that will do it + // when things have cooled down. + notifier->m_networkStateChangeTimer.startOneShot(StateChangeTimerInterval); +} + +void NetworkStateNotifier::networkStateChangeTimerFired(Timer<NetworkStateNotifier>*) +{ + bool oldOnLine = m_isOnLine; + + updateState(); + + if (m_isOnLine == oldOnLine) + return; + + if (m_networkStateChangedFunction) + m_networkStateChangedFunction(); +} + +NetworkStateNotifier::NetworkStateNotifier() + : m_isOnLine(false) + , m_networkStateChangeTimer(this, &NetworkStateNotifier::networkStateChangeTimerFired) +{ + SCDynamicStoreContext context = { 0, this, 0, 0, 0 }; + + m_store.adoptCF(SCDynamicStoreCreate(0, CFSTR("com.apple.WebCore"), dynamicStoreCallback, &context)); + if (!m_store) + return; + + RetainPtr<CFRunLoopSourceRef> configSource = SCDynamicStoreCreateRunLoopSource(0, m_store.get(), 0); + if (!configSource) + return; + + CFRunLoopAddSource(CFRunLoopGetCurrent(), configSource.get(), kCFRunLoopCommonModes); + + RetainPtr<CFMutableArrayRef> keys(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks)); + RetainPtr<CFMutableArrayRef> patterns(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks)); + + RetainPtr<CFStringRef> key; + RetainPtr<CFStringRef> pattern; + + key.adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetIPv4)); + CFArrayAppendValue(keys.get(), key.get()); + + pattern.adoptCF(SCDynamicStoreKeyCreateNetworkInterfaceEntity(0, kSCDynamicStoreDomainState, kSCCompAnyRegex, kSCEntNetIPv4)); + CFArrayAppendValue(patterns.get(), pattern.get()); + + key.adoptCF(SCDynamicStoreKeyCreateNetworkGlobalEntity(0, kSCDynamicStoreDomainState, kSCEntNetDNS)); + CFArrayAppendValue(keys.get(), key.get()); + + SCDynamicStoreSetNotificationKeys(m_store.get(), keys.get(), patterns.get()); + + updateState(); +} + +} diff --git a/WebCore/platform/network/mac/ResourceError.h b/WebCore/platform/network/mac/ResourceError.h new file mode 100644 index 0000000..2f779c9 --- /dev/null +++ b/WebCore/platform/network/mac/ResourceError.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceError_h +#define ResourceError_h + +#include "ResourceErrorBase.h" +#include <wtf/RetainPtr.h> + +#ifdef __OBJC__ +@class NSError; +#else +class NSError; +#endif + +namespace WebCore { + + class ResourceError : public ResourceErrorBase { + public: + ResourceError() + : m_dataIsUpToDate(true) + { + } + + ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) + , m_dataIsUpToDate(true) + { + } + + ResourceError(NSError* error) + : m_dataIsUpToDate(false) + , m_platformError(error) + { + m_isNull = !error; + } + + operator NSError*() const; + + private: + friend class ResourceErrorBase; + + void platformLazyInit(); + static bool platformCompare(const ResourceError& a, const ResourceError& b); + + bool m_dataIsUpToDate; + mutable RetainPtr<NSError> m_platformError; +}; + +} // namespace WebCore + +#endif // ResourceError_h_ diff --git a/WebCore/platform/network/mac/ResourceErrorMac.mm b/WebCore/platform/network/mac/ResourceErrorMac.mm new file mode 100644 index 0000000..e59eadd --- /dev/null +++ b/WebCore/platform/network/mac/ResourceErrorMac.mm @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2006, 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#import "config.h" +#import "ResourceError.h" + +#import "KURL.h" +#import <Foundation/Foundation.h> + +@interface NSError (WebExtras) +- (NSString *)_web_localizedDescription; +@end + +namespace WebCore { + +void ResourceError::platformLazyInit() +{ + if (m_dataIsUpToDate) + return; + + m_domain = [m_platformError.get() domain]; + m_errorCode = [m_platformError.get() code]; + + NSString* failingURLString = [[m_platformError.get() userInfo] valueForKey:@"NSErrorFailingURLStringKey"]; + if (!failingURLString) + failingURLString = [[[m_platformError.get() userInfo] valueForKey:@"NSErrorFailingURLKey"] absoluteString]; + + m_localizedDescription = [m_platformError.get() _web_localizedDescription]; + + m_dataIsUpToDate = true; +} + +bool ResourceError::platformCompare(const ResourceError& a, const ResourceError& b) +{ + return (NSError*)a == (NSError*)b; +} + +ResourceError::operator NSError*() const +{ + if (m_isNull) { + ASSERT(!m_platformError); + return nil; + } + + if (!m_platformError) { + RetainPtr<NSMutableDictionary> userInfo(AdoptNS, [[NSMutableDictionary alloc] init]); + + if (!m_localizedDescription.isEmpty()) + [userInfo.get() setValue:m_localizedDescription forKey:NSLocalizedDescriptionKey]; + + if (!m_failingURL.isEmpty()) { + NSURL *cocoaURL = KURL(m_failingURL); + [userInfo.get() setValue:m_failingURL forKey:@"NSErrorFailingURLStringKey"]; + [userInfo.get() setValue:cocoaURL forKey:@"NSErrorFailingURLKey"]; + } + + m_platformError.adoptNS([[NSError alloc] initWithDomain:m_domain code:m_errorCode userInfo:userInfo.get()]); + } + + return m_platformError.get(); +} + +} // namespace WebCore diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm new file mode 100644 index 0000000..b4c5ddf --- /dev/null +++ b/WebCore/platform/network/mac/ResourceHandleMac.mm @@ -0,0 +1,779 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#import "config.h" +#import "ResourceHandle.h" +#import "ResourceHandleInternal.h" + +#import "AuthenticationChallenge.h" +#import "AuthenticationMac.h" +#import "BlockExceptions.h" +#import "DocLoader.h" +#import "FormDataStreamMac.h" +#import "Frame.h" +#import "FrameLoader.h" +#import "Page.h" +#import "ResourceError.h" +#import "ResourceResponse.h" +#import "SchedulePair.h" +#import "SharedBuffer.h" +#import "SubresourceLoader.h" +#import "WebCoreSystemInterface.h" + +#ifdef BUILDING_ON_TIGER +typedef int NSInteger; +#endif + +using namespace WebCore; + +@interface WebCoreResourceHandleAsDelegate : NSObject <NSURLAuthenticationChallengeSender> +{ + ResourceHandle* m_handle; +#ifndef BUILDING_ON_TIGER + NSURL *m_url; +#endif +} +- (id)initWithHandle:(ResourceHandle*)handle; +- (void)detachHandle; +@end + +@interface NSURLConnection (NSURLConnectionTigerPrivate) +- (NSData *)_bufferedData; +@end + +#ifndef BUILDING_ON_TIGER +@interface WebCoreSynchronousLoader : NSObject { + NSURL *m_url; + NSURLResponse *m_response; + NSMutableData *m_data; + NSError *m_error; + BOOL m_isDone; +} ++ (NSData *)loadRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error; +@end + +static NSString *WebCoreSynchronousLoaderRunLoopMode = @"WebCoreSynchronousLoaderRunLoopMode"; +#endif + +namespace WebCore { + +#ifdef BUILDING_ON_TIGER +static unsigned inNSURLConnectionCallback; +#endif + +#ifndef NDEBUG +static bool isInitializingConnection; +#endif + +class CallbackGuard { +public: + CallbackGuard() + { +#ifdef BUILDING_ON_TIGER + ++inNSURLConnectionCallback; +#endif + } + ~CallbackGuard() + { +#ifdef BUILDING_ON_TIGER + ASSERT(inNSURLConnectionCallback > 0); + --inNSURLConnectionCallback; +#endif + } +}; + +ResourceHandleInternal::~ResourceHandleInternal() +{ +} + +ResourceHandle::~ResourceHandle() +{ + releaseDelegate(); +} + +static const double MaxFoundationVersionWithoutdidSendBodyDataDelegate = 677.21; +bool ResourceHandle::didSendBodyDataDelegateExists() +{ +// FIXME: Refine this check as the delegate becomes more widely available. +#ifdef BUILDING_ON_LEOPARD + return NSFoundationVersionNumber > MaxFoundationVersionWithoutdidSendBodyDataDelegate; +#else + return false; +#endif +} + +bool ResourceHandle::start(Frame* frame) +{ + if (!frame) + return false; + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + // If we are no longer attached to a Page, this must be an attempted load from an + // onUnload handler, so let's just block it. + Page* page = frame->page(); + if (!page) + return false; + +#ifndef NDEBUG + isInitializingConnection = YES; +#endif + id delegate; + + if (d->m_mightDownloadFromHandle) { + ASSERT(!d->m_proxy); + d->m_proxy = wkCreateNSURLConnectionDelegateProxy(); + [d->m_proxy.get() setDelegate:ResourceHandle::delegate()]; + [d->m_proxy.get() release]; + + delegate = d->m_proxy.get(); + } else + delegate = ResourceHandle::delegate(); + + if (!ResourceHandle::didSendBodyDataDelegateExists()) + associateStreamWithResourceHandle([d->m_request.nsURLRequest() HTTPBodyStream], this); + + NSURLConnection *connection; + + if (d->m_shouldContentSniff) +#ifdef BUILDING_ON_TIGER + connection = [[NSURLConnection alloc] initWithRequest:d->m_request.nsURLRequest() delegate:delegate]; +#else + connection = [[NSURLConnection alloc] initWithRequest:d->m_request.nsURLRequest() delegate:delegate startImmediately:NO]; +#endif + else { + NSMutableURLRequest *request = [d->m_request.nsURLRequest() mutableCopy]; + wkSetNSURLRequestShouldContentSniff(request, NO); +#ifdef BUILDING_ON_TIGER + connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate]; +#else + connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO]; +#endif + [request release]; + } + +#ifndef BUILDING_ON_TIGER + bool scheduled = false; + if (SchedulePairHashSet* scheduledPairs = page->scheduledRunLoopPairs()) { + SchedulePairHashSet::iterator end = scheduledPairs->end(); + for (SchedulePairHashSet::iterator it = scheduledPairs->begin(); it != end; ++it) { + if (NSRunLoop *runLoop = (*it)->nsRunLoop()) { + [connection scheduleInRunLoop:runLoop forMode:(NSString *)(*it)->mode()]; + scheduled = true; + } + } + } + + // Start the connection if we did schedule with at least one runloop. + // We can't start the connection until we have one runloop scheduled. + if (scheduled) + [connection start]; + else + d->m_startWhenScheduled = true; +#endif + +#ifndef NDEBUG + isInitializingConnection = NO; +#endif + + d->m_connection = connection; + + if (d->m_connection) { + [connection release]; + + if (d->m_defersLoading) + wkSetNSURLConnectionDefersCallbacks(d->m_connection.get(), YES); + + return true; + } + + END_BLOCK_OBJC_EXCEPTIONS; + + return false; +} + +void ResourceHandle::cancel() +{ + if (!ResourceHandle::didSendBodyDataDelegateExists()) + disassociateStreamWithResourceHandle([d->m_request.nsURLRequest() HTTPBodyStream]); + [d->m_connection.get() cancel]; +} + +void ResourceHandle::setDefersLoading(bool defers) +{ + d->m_defersLoading = defers; + if (d->m_connection) + wkSetNSURLConnectionDefersCallbacks(d->m_connection.get(), defers); +} + +void ResourceHandle::schedule(SchedulePair* pair) +{ +#ifndef BUILDING_ON_TIGER + NSRunLoop *runLoop = pair->nsRunLoop(); + if (!runLoop) + return; + [d->m_connection.get() scheduleInRunLoop:runLoop forMode:(NSString *)pair->mode()]; + if (d->m_startWhenScheduled) { + [d->m_connection.get() start]; + d->m_startWhenScheduled = false; + } +#endif +} + +void ResourceHandle::unschedule(SchedulePair* pair) +{ +#ifndef BUILDING_ON_TIGER + if (NSRunLoop *runLoop = pair->nsRunLoop()) + [d->m_connection.get() unscheduleFromRunLoop:runLoop forMode:(NSString *)pair->mode()]; +#endif +} + +WebCoreResourceHandleAsDelegate *ResourceHandle::delegate() +{ + if (!d->m_delegate) { + WebCoreResourceHandleAsDelegate *delegate = [[WebCoreResourceHandleAsDelegate alloc] initWithHandle:this]; + d->m_delegate = delegate; + [delegate release]; + } + return d->m_delegate.get(); +} + +void ResourceHandle::releaseDelegate() +{ + if (!d->m_delegate) + return; + if (d->m_proxy) + [d->m_proxy.get() setDelegate:nil]; + [d->m_delegate.get() detachHandle]; + d->m_delegate = nil; +} + +bool ResourceHandle::supportsBufferedData() +{ + static bool supportsBufferedData = [NSURLConnection instancesRespondToSelector:@selector(_bufferedData)]; + return supportsBufferedData; +} + +PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() +{ + if (ResourceHandle::supportsBufferedData()) + return SharedBuffer::wrapNSData([d->m_connection.get() _bufferedData]); + + return 0; +} + +id ResourceHandle::releaseProxy() +{ + id proxy = [[d->m_proxy.get() retain] autorelease]; + d->m_proxy = nil; + [proxy setDelegate:nil]; + return proxy; +} + +NSURLConnection *ResourceHandle::connection() const +{ + return d->m_connection.get(); +} + +bool ResourceHandle::loadsBlocked() +{ +#ifndef BUILDING_ON_TIGER + return false; +#else + // On Tiger, if we're in an NSURLConnection callback, that blocks all other NSURLConnection callbacks. + // On Leopard and newer, it blocks only callbacks on that same NSURLConnection object, which is not + // a problem in practice. + return inNSURLConnectionCallback != 0; +#endif +} + +bool ResourceHandle::willLoadFromCache(ResourceRequest& request) +{ + request.setCachePolicy(ReturnCacheDataDontLoad); + NSURLResponse *nsURLResponse = nil; + BEGIN_BLOCK_OBJC_EXCEPTIONS; + + [NSURLConnection sendSynchronousRequest:request.nsURLRequest() returningResponse:&nsURLResponse error:nil]; + + END_BLOCK_OBJC_EXCEPTIONS; + + return nsURLResponse; +} + +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame*) +{ + NSError *nsError = nil; + + NSURLResponse *nsURLResponse = nil; + NSData *result = nil; + + ASSERT(!request.isEmpty()); + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + +#ifndef BUILDING_ON_TIGER + result = [WebCoreSynchronousLoader loadRequest:request.nsURLRequest() returningResponse:&nsURLResponse error:&nsError]; +#else + result = [NSURLConnection sendSynchronousRequest:request.nsURLRequest() returningResponse:&nsURLResponse error:&nsError]; +#endif + END_BLOCK_OBJC_EXCEPTIONS; + + if (nsError == nil) + response = nsURLResponse; + else { + response = ResourceResponse(request.url(), String(), 0, String(), String()); + if ([nsError domain] == NSURLErrorDomain) + switch ([nsError code]) { + case NSURLErrorUserCancelledAuthentication: + // FIXME: we should really return the actual HTTP response, but sendSynchronousRequest doesn't provide us with one. + response.setHTTPStatusCode(401); + break; + default: + response.setHTTPStatusCode([nsError code]); + } + else + response.setHTTPStatusCode(404); + } + + data.resize([result length]); + memcpy(data.data(), [result bytes], [result length]); + + error = nsError; +} + +void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) +{ + ASSERT(!d->m_currentMacChallenge); + ASSERT(d->m_currentWebChallenge.isNull()); + // Since NSURLConnection networking relies on keeping a reference to the original NSURLAuthenticationChallenge, + // we make sure that is actually present + ASSERT(challenge.nsURLAuthenticationChallenge()); + + d->m_currentMacChallenge = challenge.nsURLAuthenticationChallenge(); + NSURLAuthenticationChallenge *webChallenge = [[NSURLAuthenticationChallenge alloc] initWithAuthenticationChallenge:d->m_currentMacChallenge + sender:(id<NSURLAuthenticationChallengeSender>)delegate()]; + d->m_currentWebChallenge = core(webChallenge); + [webChallenge release]; + + if (client()) + client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge); +} + +void ResourceHandle::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge) +{ + ASSERT(d->m_currentMacChallenge); + ASSERT(!d->m_currentWebChallenge.isNull()); + ASSERT(d->m_currentWebChallenge == challenge); + + if (client()) + client()->didCancelAuthenticationChallenge(this, d->m_currentWebChallenge); +} + +void ResourceHandle::receivedCredential(const AuthenticationChallenge& challenge, const Credential& credential) +{ + ASSERT(!challenge.isNull()); + if (challenge != d->m_currentWebChallenge) + return; + + [[d->m_currentMacChallenge sender] useCredential:mac(credential) forAuthenticationChallenge:d->m_currentMacChallenge]; + + clearAuthentication(); +} + +void ResourceHandle::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge& challenge) +{ + ASSERT(!challenge.isNull()); + if (challenge != d->m_currentWebChallenge) + return; + + [[d->m_currentMacChallenge sender] continueWithoutCredentialForAuthenticationChallenge:d->m_currentMacChallenge]; + + clearAuthentication(); +} + +void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challenge) +{ + if (challenge != d->m_currentWebChallenge) + return; + + if (client()) + client()->receivedCancellation(this, challenge); +} + +} // namespace WebCore + +@implementation WebCoreResourceHandleAsDelegate + +- (id)initWithHandle:(ResourceHandle*)handle +{ + self = [self init]; + if (!self) + return nil; + m_handle = handle; + return self; +} + +#ifndef BUILDING_ON_TIGER +- (void)dealloc +{ + [m_url release]; + [super dealloc]; +} +#endif + +- (void)detachHandle +{ + m_handle = 0; +} + +- (NSURLRequest *)connection:(NSURLConnection *)con willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse +{ + // the willSendRequest call may cancel this load, in which case self could be deallocated + RetainPtr<WebCoreResourceHandleAsDelegate> protect(self); + + if (!m_handle || !m_handle->client()) + return nil; + + // See <rdar://problem/5380697> . This is a workaround for a behavior change in CFNetwork where willSendRequest gets called more often. + if (!redirectResponse) + return newRequest; + + CallbackGuard guard; + ResourceRequest request = newRequest; + m_handle->client()->willSendRequest(m_handle, request, redirectResponse); +#ifndef BUILDING_ON_TIGER + NSURL *copy = [[request.nsURLRequest() URL] copy]; + [m_url release]; + m_url = copy; +#endif + + if (!ResourceHandle::didSendBodyDataDelegateExists()) { + // The client may change the request's body stream, in which case we have to re-associate + // the handle with the new stream so upload progress callbacks continue to work correctly. + NSInputStream* oldBodyStream = [newRequest HTTPBodyStream]; + NSInputStream* newBodyStream = [request.nsURLRequest() HTTPBodyStream]; + if (oldBodyStream != newBodyStream) { + disassociateStreamWithResourceHandle(oldBodyStream); + associateStreamWithResourceHandle(newBodyStream, m_handle); + } + } + + return request.nsURLRequest(); +} + +- (void)connection:(NSURLConnection *)con didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +{ +#ifndef BUILDING_ON_TIGER + if ([challenge previousFailureCount] == 0) { + NSString *user = [m_url user]; + NSString *password = [m_url password]; + + if (user && password) { + NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:user + password:password + persistence:NSURLCredentialPersistenceForSession]; + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + [credential release]; + return; + } + } +#endif + + if (!m_handle) + return; + CallbackGuard guard; + m_handle->didReceiveAuthenticationChallenge(core(challenge)); +} + +- (void)connection:(NSURLConnection *)con didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +{ + if (!m_handle) + return; + CallbackGuard guard; + m_handle->didCancelAuthenticationChallenge(core(challenge)); +} + +- (void)connection:(NSURLConnection *)con didReceiveResponse:(NSURLResponse *)r +{ + if (!m_handle || !m_handle->client()) + return; + CallbackGuard guard; + m_handle->client()->didReceiveResponse(m_handle, r); +} + +- (void)connection:(NSURLConnection *)con didReceiveData:(NSData *)data lengthReceived:(long long)lengthReceived +{ + if (!m_handle || !m_handle->client()) + return; + // FIXME: If we get more than 2B bytes in a single chunk, this code won't do the right thing. + // However, with today's computers and networking speeds, this won't happen in practice. + // Could be an issue with a giant local file. + CallbackGuard guard; + m_handle->client()->didReceiveData(m_handle, (const char*)[data bytes], [data length], static_cast<int>(lengthReceived)); +} + +- (void)connection:(NSURLConnection *)con willStopBufferingData:(NSData *)data +{ + if (!m_handle || !m_handle->client()) + return; + // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. + // However, with today's computers and networking speeds, this won't happen in practice. + // Could be an issue with a giant local file. + CallbackGuard guard; + m_handle->client()->willStopBufferingData(m_handle, (const char*)[data bytes], static_cast<int>([data length])); +} + +- (void)connection:(NSURLConnection *)connection didSendBodyData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite +{ + if (!m_handle || !m_handle->client()) + return; + CallbackGuard guard; + m_handle->client()->didSendData(m_handle, totalBytesWritten, totalBytesExpectedToWrite); +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)con +{ + if (!m_handle || !m_handle->client()) + return; + CallbackGuard guard; + + if (!ResourceHandle::didSendBodyDataDelegateExists()) + disassociateStreamWithResourceHandle([m_handle->request().nsURLRequest() HTTPBodyStream]); + + m_handle->client()->didFinishLoading(m_handle); +} + +- (void)connection:(NSURLConnection *)con didFailWithError:(NSError *)error +{ + if (!m_handle || !m_handle->client()) + return; + CallbackGuard guard; + + if (!ResourceHandle::didSendBodyDataDelegateExists()) + disassociateStreamWithResourceHandle([m_handle->request().nsURLRequest() HTTPBodyStream]); + + m_handle->client()->didFail(m_handle, error); +} + +#ifdef BUILDING_ON_TIGER +- (void)_callConnectionWillCacheResponseWithInfo:(NSMutableDictionary *)info +{ + NSURLConnection *connection = [info objectForKey:@"connection"]; + NSCachedURLResponse *cachedResponse = [info objectForKey:@"cachedResponse"]; + NSCachedURLResponse *result = [self connection:connection willCacheResponse:cachedResponse]; + if (result) + [info setObject:result forKey:@"result"]; +} +#endif + +- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse +{ +#ifdef BUILDING_ON_TIGER + // On Tiger CFURLConnection can sometimes call the connection:willCacheResponse: delegate method on + // a secondary thread instead of the main thread. If this happens perform the work on the main thread. + if (!pthread_main_np()) { + NSMutableDictionary *info = [[NSMutableDictionary alloc] init]; + if (connection) + [info setObject:connection forKey:@"connection"]; + if (cachedResponse) + [info setObject:cachedResponse forKey:@"cachedResponse"]; + + // Include synchronous url connection's mode as an acceptable run loopmode + // <rdar://problem/5511842> + NSArray *modes = [[NSArray alloc] initWithObjects:(NSString *)kCFRunLoopCommonModes, @"NSSynchronousURLConnection_PrivateMode", nil]; + [self performSelectorOnMainThread:@selector(_callConnectionWillCacheResponseWithInfo:) withObject:info waitUntilDone:YES modes:modes]; + [modes release]; + + NSCachedURLResponse *result = [[info valueForKey:@"result"] retain]; + [info release]; + + return [result autorelease]; + } +#endif + +#ifndef NDEBUG + if (isInitializingConnection) + LOG_ERROR("connection:willCacheResponse: was called inside of [NSURLConnection initWithRequest:delegate:] (4067625)"); +#endif + if (!m_handle || !m_handle->client()) + return nil; + + CallbackGuard guard; + + NSCachedURLResponse *newResponse = m_handle->client()->willCacheResponse(m_handle, cachedResponse); + if (newResponse != cachedResponse) + return newResponse; + + CacheStoragePolicy policy = static_cast<CacheStoragePolicy>([newResponse storagePolicy]); + + m_handle->client()->willCacheResponse(m_handle, policy); + + if (static_cast<NSURLCacheStoragePolicy>(policy) != [newResponse storagePolicy]) + newResponse = [[[NSCachedURLResponse alloc] initWithResponse:[newResponse response] + data:[newResponse data] + userInfo:[newResponse userInfo] + storagePolicy:static_cast<NSURLCacheStoragePolicy>(policy)] autorelease]; + + 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 +@implementation WebCoreSynchronousLoader + +- (BOOL)_isDone +{ + return m_isDone; +} + +- (void)dealloc +{ + [m_url release]; + [m_response release]; + [m_data release]; + [m_error release]; + + [super dealloc]; +} + +- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)newRequest redirectResponse:(NSURLResponse *)redirectResponse +{ + NSURL *copy = [[newRequest URL] copy]; + [m_url release]; + m_url = copy; + + return newRequest; +} + +- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge +{ + if ([challenge previousFailureCount] == 0) { + NSString *user = [m_url user]; + NSString *password = [m_url password]; + + if (user && password) { + NSURLCredential *credential = [[NSURLCredential alloc] initWithUser:user + password:password + persistence:NSURLCredentialPersistenceForSession]; + [[challenge sender] useCredential:credential forAuthenticationChallenge:challenge]; + [credential release]; + return; + } + } + + [[challenge sender] continueWithoutCredentialForAuthenticationChallenge:challenge]; +} + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response +{ + NSURLResponse *r = [response copy]; + + [m_response release]; + m_response = r; +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data +{ + if (!m_data) + m_data = [[NSMutableData alloc] init]; + + [m_data appendData:data]; +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection +{ + m_isDone = YES; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error +{ + ASSERT(!m_error); + + m_error = [error retain]; + m_isDone = YES; +} + +- (NSData *)_data +{ + return [[m_data retain] autorelease]; +} + +- (NSURLResponse *)_response +{ + return [[m_response retain] autorelease]; +} + +- (NSError *)_error +{ + return [[m_error retain] autorelease]; +} + ++ (NSData *)loadRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error +{ + WebCoreSynchronousLoader *delegate = [[WebCoreSynchronousLoader alloc] init]; + + NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate startImmediately:NO]; + [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:WebCoreSynchronousLoaderRunLoopMode]; + [connection start]; + + while (![delegate _isDone]) + [[NSRunLoop currentRunLoop] runMode:WebCoreSynchronousLoaderRunLoopMode beforeDate:[NSDate distantFuture]]; + + NSData *data = [delegate _data]; + *response = [delegate _response]; + *error = [delegate _error]; + + [connection cancel]; + + [connection release]; + [delegate release]; + + return data; +} + +@end +#endif diff --git a/WebCore/platform/network/mac/ResourceRequest.h b/WebCore/platform/network/mac/ResourceRequest.h new file mode 100644 index 0000000..5bcb33e --- /dev/null +++ b/WebCore/platform/network/mac/ResourceRequest.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequest_h +#define ResourceRequest_h + +#include "ResourceRequestBase.h" + +#include <wtf/RetainPtr.h> +#ifdef __OBJC__ +@class NSURLRequest; +#else +class NSURLRequest; +#endif + +namespace WebCore { + + class ResourceRequest : public ResourceRequestBase { + public: + ResourceRequest(const String& url) + : ResourceRequestBase(KURL(url), UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url) + : ResourceRequestBase(url, UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy) + : ResourceRequestBase(url, policy) + { + setHTTPReferrer(referrer); + } + + ResourceRequest() + : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + { + } + + ResourceRequest(NSURLRequest* nsRequest) + : ResourceRequestBase() + , m_nsRequest(nsRequest) { } + + void applyWebArchiveHackForMail(); + NSURLRequest* nsURLRequest() const; + + private: + friend class ResourceRequestBase; + + void doUpdatePlatformRequest(); + void doUpdateResourceRequest(); + + RetainPtr<NSURLRequest> m_nsRequest; + }; + +} // namespace WebCore + +#endif // ResourceRequest_h diff --git a/WebCore/platform/network/mac/ResourceRequestMac.mm b/WebCore/platform/network/mac/ResourceRequestMac.mm new file mode 100644 index 0000000..63fffe1 --- /dev/null +++ b/WebCore/platform/network/mac/ResourceRequestMac.mm @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#import "config.h" +#import "ResourceRequest.h" +#import "WebCoreSystemInterface.h" + +#import "FormDataStreamMac.h" + +#import <Foundation/Foundation.h> + +namespace WebCore { + +NSURLRequest* ResourceRequest::nsURLRequest() const +{ + updatePlatformRequest(); + + return [[m_nsRequest.get() retain] autorelease]; +} + +void ResourceRequest::doUpdateResourceRequest() +{ + m_url = [m_nsRequest.get() URL]; + m_cachePolicy = (ResourceRequestCachePolicy)[m_nsRequest.get() cachePolicy]; + m_timeoutInterval = [m_nsRequest.get() timeoutInterval]; + m_mainDocumentURL = [m_nsRequest.get() mainDocumentURL]; + + if (NSString* method = [m_nsRequest.get() HTTPMethod]) + m_httpMethod = method; + m_allowHTTPCookies = [m_nsRequest.get() HTTPShouldHandleCookies]; + + NSDictionary *headers = [m_nsRequest.get() allHTTPHeaderFields]; + NSEnumerator *e = [headers keyEnumerator]; + NSString *name; + while ((name = [e nextObject])) + m_httpHeaderFields.set(name, [headers objectForKey:name]); + + if (NSData* bodyData = [m_nsRequest.get() HTTPBody]) + m_httpBody = FormData::create([bodyData bytes], [bodyData length]); + else if (NSInputStream* bodyStream = [m_nsRequest.get() HTTPBodyStream]) + if (FormData* formData = httpBodyFromStream(bodyStream)) + m_httpBody = formData; +} + +void ResourceRequest::doUpdatePlatformRequest() +{ + if (isNull()) { + m_nsRequest = nil; + return; + } + + NSMutableURLRequest* nsRequest = [m_nsRequest.get() mutableCopy]; + + if (nsRequest) + [nsRequest setURL:url()]; + else + nsRequest = [[NSMutableURLRequest alloc] initWithURL:url()]; + +#ifdef BUILDING_ON_TIGER + wkSupportsMultipartXMixedReplace(nsRequest); +#endif + + [nsRequest setCachePolicy:(NSURLRequestCachePolicy)cachePolicy()]; + if (timeoutInterval() != unspecifiedTimeoutInterval) + [nsRequest setTimeoutInterval:timeoutInterval()]; + [nsRequest setMainDocumentURL:mainDocumentURL()]; + if (!httpMethod().isEmpty()) + [nsRequest setHTTPMethod:httpMethod()]; + [nsRequest setHTTPShouldHandleCookies:allowHTTPCookies()]; + + HTTPHeaderMap::const_iterator end = httpHeaderFields().end(); + for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != end; ++it) + [nsRequest setValue:it->second forHTTPHeaderField:it->first]; + + RefPtr<FormData> formData = httpBody(); + if (formData && !formData->isEmpty()) + WebCore::setHTTPBody(nsRequest, formData); + + m_nsRequest.adoptNS(nsRequest); +} + +void ResourceRequest::applyWebArchiveHackForMail() +{ + // Hack because Mail checks for this property to detect data / archive loads + [NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)nsURLRequest()]; +} + +} diff --git a/WebCore/platform/network/mac/ResourceResponse.h b/WebCore/platform/network/mac/ResourceResponse.h new file mode 100644 index 0000000..b65760c --- /dev/null +++ b/WebCore/platform/network/mac/ResourceResponse.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponse_h +#define ResourceResponse_h + +#include "ResourceResponseBase.h" +#include <wtf/RetainPtr.h> + +#ifdef __OBJC__ +@class NSURLResponse; +#else +class NSURLResponse; +#endif + +namespace WebCore { + +class ResourceResponse : public ResourceResponseBase { +public: + ResourceResponse() + : m_isUpToDate(true) + { + } + + ResourceResponse(NSURLResponse* nsResponse) + : m_nsResponse(nsResponse) + , m_isUpToDate(false) + { + m_isNull = !nsResponse; + } + + ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename) + : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename) + , m_isUpToDate(true) + { + } + + NSURLResponse *nsURLResponse() const; + +private: + friend class ResourceResponseBase; + + void platformLazyInit(); + static bool platformCompare(const ResourceResponse& a, const ResourceResponse& b); + + RetainPtr<NSURLResponse> m_nsResponse; + bool m_isUpToDate; +}; + +} // namespace WebCore + +#endif // ResourceResponse_h diff --git a/WebCore/platform/network/mac/ResourceResponseMac.mm b/WebCore/platform/network/mac/ResourceResponseMac.mm new file mode 100644 index 0000000..f60b496 --- /dev/null +++ b/WebCore/platform/network/mac/ResourceResponseMac.mm @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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. + */ + +#import "config.h" +#import "ResourceResponse.h" + +#import "WebCoreURLResponse.h" +#import <Foundation/Foundation.h> +#import <limits> + +@interface NSURLResponse (FoundationSecretsWebCoreKnowsAbout) +- (NSTimeInterval)_calculatedExpiration; +@end + +#ifdef BUILDING_ON_TIGER +typedef int NSInteger; +#endif + +namespace WebCore { + +NSURLResponse *ResourceResponse::nsURLResponse() const +{ + if (!m_nsResponse && !m_isNull) { + // Work around a mistake in the NSURLResponse class. + // The init function takes an NSInteger, even though the accessor returns a long long. + // For values that won't fit in an NSInteger, pass -1 instead. + NSInteger expectedContentLength; + if (m_expectedContentLength < 0 || m_expectedContentLength > std::numeric_limits<NSInteger>::max()) + expectedContentLength = -1; + else + expectedContentLength = static_cast<NSInteger>(m_expectedContentLength); + const_cast<ResourceResponse*>(this)->m_nsResponse.adoptNS([[NSURLResponse alloc] initWithURL:m_url MIMEType:m_mimeType expectedContentLength:expectedContentLength textEncodingName:m_textEncodingName]); + } + return m_nsResponse.get(); +} + +void ResourceResponse::platformLazyInit() +{ + if (m_isUpToDate) + return; + m_isUpToDate = true; + + if (m_isNull) { + ASSERT(!m_nsResponse); + return; + } + + m_url = [m_nsResponse.get() URL]; + m_mimeType = [m_nsResponse.get() _webcore_MIMEType]; + m_expectedContentLength = [m_nsResponse.get() expectedContentLength]; + m_textEncodingName = [m_nsResponse.get() textEncodingName]; + m_suggestedFilename = [m_nsResponse.get() suggestedFilename]; + + const time_t maxTime = std::numeric_limits<time_t>::max(); + + NSTimeInterval expiration = [m_nsResponse.get() _calculatedExpiration]; + expiration += kCFAbsoluteTimeIntervalSince1970; + m_expirationDate = expiration > maxTime ? maxTime : static_cast<time_t>(expiration); + + if ([m_nsResponse.get() isKindOfClass:[NSHTTPURLResponse class]]) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)m_nsResponse.get(); + + m_httpStatusCode = [httpResponse statusCode]; + + // FIXME: it would be nice to have a way to get the real status text eventually. + m_httpStatusText = "OK"; + + NSDictionary *headers = [httpResponse allHeaderFields]; + NSEnumerator *e = [headers keyEnumerator]; + while (NSString *name = [e nextObject]) + m_httpHeaderFields.set(name, [headers objectForKey:name]); + } else { + m_httpStatusCode = 0; + +#ifndef BUILDING_ON_TIGER + // FIXME: This is a work around for <rdar://problem/5230154> (-[NSURLConnection initWithRequest:delegate:] + // is returning incorrect MIME type for local .xhtml files) which is only required in Leopard. + if (m_url.isLocalFile() && m_mimeType == "text/html") { + const String& path = m_url.path(); + static const String xhtmlExt(".xhtml"); + if (path.endsWith(xhtmlExt, false)) + m_mimeType = "application/xhtml+xml"; + } +#endif + } +} + +bool ResourceResponse::platformCompare(const ResourceResponse& a, const ResourceResponse& b) +{ + return a.nsURLResponse() == b.nsURLResponse(); +} + +} diff --git a/WebCore/platform/network/mac/WebCoreURLResponse.h b/WebCore/platform/network/mac/WebCoreURLResponse.h new file mode 100644 index 0000000..a06ab70 --- /dev/null +++ b/WebCore/platform/network/mac/WebCoreURLResponse.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2008 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +// FIXME: This is a workaround for <rdar://problem/5321972> REGRESSION: Plain text document from HTTP server detected +// as application/octet-stream + +@interface NSURLResponse (WebCoreURLResponse) +- (NSString *)_webcore_MIMEType; +@end diff --git a/WebCore/platform/network/mac/WebCoreURLResponse.mm b/WebCore/platform/network/mac/WebCoreURLResponse.mm new file mode 100644 index 0000000..b8843af --- /dev/null +++ b/WebCore/platform/network/mac/WebCoreURLResponse.mm @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2008 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 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. + */ + +#import "config.h" + +#import "WebCoreURLResponse.h" + +#ifndef BUILDING_ON_TIGER +static NSSet *createBinaryExtensionsSet() +{ + return [[NSSet alloc] initWithObjects: + @"3g2", + @"3gp", + @"ai", + @"aif", + @"aifc", + @"aiff", + @"au", + @"avi", + @"bcpio", + @"bin", + @"bmp", + @"boz", + @"bpk", + @"bz", + @"bz2", + @"chm", + @"class", + @"com", + @"cpio", + @"dcr", + @"dir", + @"dist", + @"distz", + @"dll", + @"dmg", + @"dms", + @"doc", + @"dot", + @"dump", + @"dv", + @"dvi", + @"dxr", + @"elc", + @"eot", + @"eps", + @"exe", + @"fgd", + @"gif", + @"gtar", + @"h261", + @"h263", + @"h264", + @"ico", + @"ims", + @"indd", + @"iso", + @"jp2", + @"jpe", + @"jpeg", + @"jpg", + @"jpgm", + @"jpgv", + @"jpm", + @"kar", + @"lha", + @"lrm", + @"lzh", + @"m1v", + @"m2a", + @"m2v", + @"m3a", + @"m3u", + @"m4a", + @"m4p", + @"m4v", + @"mdb", + @"mid", + @"midi", + @"mj2", + @"mjp2", + @"mov", + @"movie", + @"mp2", + @"mp2a", + @"mp3", + @"mp4", + @"mp4a", + @"mp4s", + @"mp4v", + @"mpe", + @"mpeg", + @"mpg", + @"mpg4", + @"mpga", + @"mpp", + @"mpt", + @"msi", + @"ogg", + @"otf", + @"pct", + @"pdf", + @"pfa", + @"pfb", + @"pic", + @"pict", + @"pkg", + @"png", + @"pot", + @"pps", + @"ppt", + @"ps", + @"psd", + @"qt", + @"qti", + @"qtif", + @"qwd", + @"qwt", + @"qxb", + @"qxd", + @"qxl", + @"qxp", + @"qxt", + @"ra", + @"ram", + @"rm", + @"rmi", + @"rmp", + @"scpt", + @"sit", + @"sitx", + @"snd", + @"so", + @"swf", + @"tar", + @"tif", + @"tiff", + @"ttf", + @"wav", + @"wcm", + @"wdb", + @"wks", + @"wm", + @"wma", + @"wmd", + @"wmf", + @"wmv", + @"wmx", + @"wmz", + @"wpd", + @"wpl", + @"wps", + @"wvx", + @"xla", + @"xlc", + @"xlm", + @"xls", + @"xlt", + @"xlw", + @"xps", + @"zip", + nil + ]; +} +#endif + +@implementation NSURLResponse (WebCoreURLResponse) + +- (NSString *)_webcore_MIMEType +{ + NSString *MIMEType = [self MIMEType]; +#ifdef BUILDING_ON_LEOPARD + // Workaround for <rdar://problem/5539824> + if ([MIMEType isEqualToString:@"text/xml"]) + return @"application/xml"; +#endif + return MIMEType; +} + +@end + +@implementation NSHTTPURLResponse (WebCoreURLResponse) + +- (NSString *)_webcore_MIMEType +{ + NSString *MIMEType = [self MIMEType]; +#ifndef BUILDING_ON_TIGER + if ([MIMEType isEqualToString:@"application/octet-stream"] && [[[self allHeaderFields] objectForKey:@"Content-Type"] hasPrefix:@"text/plain"]) { + static NSSet *binaryExtensions = createBinaryExtensionsSet(); + return [binaryExtensions containsObject:[[[self suggestedFilename] pathExtension] lowercaseString]] ? MIMEType : @"text/plain"; + } +#endif + return MIMEType; +} + +@end diff --git a/WebCore/platform/network/qt/AuthenticationChallenge.h b/WebCore/platform/network/qt/AuthenticationChallenge.h new file mode 100644 index 0000000..753ac6f --- /dev/null +++ b/WebCore/platform/network/qt/AuthenticationChallenge.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" + +namespace WebCore { + +class AuthenticationChallenge : public AuthenticationChallengeBase { +public: + AuthenticationChallenge() + { + } + + AuthenticationChallenge(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error) + : AuthenticationChallengeBase(protectionSpace, proposedCredential, previousFailureCount, response, error) + { + } +}; + +} + +#endif diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp new file mode 100644 index 0000000..2de2125 --- /dev/null +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp @@ -0,0 +1,435 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2007 Staikos Computing Services Inc. <info@staikos.net> + Copyright (C) 2008 Holger Hans Peter Freyther + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include "config.h" +#include "QNetworkReplyHandler.h" + +#if QT_VERSION >= 0x040400 + +#include "HTTPParsers.h" +#include "MIMETypeRegistry.h" +#include "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "ResourceResponse.h" +#include "ResourceRequest.h" +#include <QDateTime> +#include <QFile> +#include <QNetworkReply> +#include <QNetworkCookie> +#include <qwebframe.h> +#include <qwebpage.h> + +#include <QDebug> +#include <QCoreApplication> + +namespace WebCore { + +// Take a deep copy of the FormDataElement +FormDataIODevice::FormDataIODevice(FormData* data) + : m_formElements(data ? data->elements() : Vector<FormDataElement>()) + , m_currentFile(0) + , m_currentDelta(0) +{ + setOpenMode(FormDataIODevice::ReadOnly); +} + +FormDataIODevice::~FormDataIODevice() +{ + delete m_currentFile; +} + +void FormDataIODevice::moveToNextElement() +{ + if (m_currentFile) + m_currentFile->close(); + m_currentDelta = 0; + + m_formElements.remove(0); + + if (m_formElements.isEmpty() || m_formElements[0].m_type == FormDataElement::data) + return; + + if (!m_currentFile) + m_currentFile = new QFile; + + m_currentFile->setFileName(m_formElements[0].m_filename); + m_currentFile->open(QFile::ReadOnly); +} + +// m_formElements[0] is the current item. If the destination buffer is +// big enough we are going to read from more than one FormDataElement +qint64 FormDataIODevice::readData(char* destination, qint64 size) +{ + if (m_formElements.isEmpty()) + return -1; + + qint64 copied = 0; + while (copied < size && !m_formElements.isEmpty()) { + const FormDataElement& element = m_formElements[0]; + const qint64 available = size-copied; + + if (element.m_type == FormDataElement::data) { + const qint64 toCopy = qMin<qint64>(available, element.m_data.size() - m_currentDelta); + memcpy(destination+copied, element.m_data.data()+m_currentDelta, toCopy); + m_currentDelta += toCopy; + copied += toCopy; + + if (m_currentDelta == element.m_data.size()) + moveToNextElement(); + } else { + const QByteArray data = m_currentFile->read(available); + memcpy(destination+copied, data.constData(), data.size()); + copied += data.size(); + + if (m_currentFile->atEnd() || !m_currentFile->isOpen()) + moveToNextElement(); + } + } + + return copied; +} + +qint64 FormDataIODevice::writeData(const char*, qint64) +{ + return -1; +} + +void FormDataIODevice::setParent(QNetworkReply* reply) +{ + QIODevice::setParent(reply); + + connect(reply, SIGNAL(finished()), SLOT(slotFinished()), Qt::QueuedConnection); +} + +bool FormDataIODevice::isSequential() const +{ + return true; +} + +void FormDataIODevice::slotFinished() +{ + deleteLater(); +} + +QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode loadMode) + : QObject(0) + , m_resourceHandle(handle) + , m_reply(0) + , m_redirected(false) + , m_responseSent(false) + , m_loadMode(loadMode) + , m_startTime(0) + , m_shouldStart(true) + , m_shouldFinish(false) + , m_shouldSendResponse(false) + , m_shouldForwardData(false) +{ + const ResourceRequest &r = m_resourceHandle->request(); + + if (r.httpMethod() == "GET") + m_method = QNetworkAccessManager::GetOperation; + else if (r.httpMethod() == "HEAD") + m_method = QNetworkAccessManager::HeadOperation; + else if (r.httpMethod() == "POST") + m_method = QNetworkAccessManager::PostOperation; + else if (r.httpMethod() == "PUT") + m_method = QNetworkAccessManager::PutOperation; + else + m_method = QNetworkAccessManager::UnknownOperation; + + m_request = r.toNetworkRequest(); + + if (m_loadMode == LoadNormal) + start(); +} + +void QNetworkReplyHandler::setLoadMode(LoadMode mode) +{ + m_loadMode = mode; + if (m_loadMode == LoadNormal) + sendQueuedItems(); +} + +void QNetworkReplyHandler::abort() +{ + m_resourceHandle = 0; + if (m_reply) { + QNetworkReply* reply = release(); + reply->abort(); + deleteLater(); + } +} + +QNetworkReply* QNetworkReplyHandler::release() +{ + QNetworkReply* reply = m_reply; + if (m_reply) { + disconnect(m_reply, 0, this, 0); + // We have queued connections to the QNetworkReply. Make sure any + // posted meta call events that were the result of a signal emission + // don't reach the slots in our instance. + QCoreApplication::removePostedEvents(this, QEvent::MetaCall); + m_reply = 0; + } + return reply; +} + +void QNetworkReplyHandler::finish() +{ + m_shouldFinish = (m_loadMode == LoadDeferred); + if (m_loadMode == LoadDeferred) + return; + + sendResponseIfNeeded(); + + if (!m_resourceHandle) + return; + ResourceHandleClient* client = m_resourceHandle->client(); + if (!client) { + m_reply->deleteLater(); + m_reply = 0; + return; + } + QNetworkReply* oldReply = m_reply; + if (m_redirected) { + resetState(); + start(); + } else if (m_reply->error() != QNetworkReply::NoError + // a web page that returns 403/404 can still have content + && m_reply->error() != QNetworkReply::ContentOperationNotPermittedError + && m_reply->error() != QNetworkReply::ContentNotFoundError) { + QUrl url = m_reply->url(); + ResourceError error(url.host(), m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), + url.toString(), m_reply->errorString()); + client->didFail(m_resourceHandle, error); + } else { + client->didFinishLoading(m_resourceHandle); + } + oldReply->deleteLater(); + if (oldReply == m_reply) + m_reply = 0; +} + +void QNetworkReplyHandler::sendResponseIfNeeded() +{ + m_shouldSendResponse = (m_loadMode == LoadDeferred); + if (m_loadMode == LoadDeferred) + return; + + if (m_responseSent || !m_resourceHandle) + return; + m_responseSent = true; + + ResourceHandleClient* client = m_resourceHandle->client(); + if (!client) + return; + + WebCore::String contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString(); + WebCore::String encoding = extractCharsetFromMediaType(contentType); + WebCore::String mimeType = extractMIMETypeFromMediaType(contentType); + + if (mimeType.isEmpty()) { + // let's try to guess from the extension + QString extension = m_reply->url().path(); + int index = extension.lastIndexOf(QLatin1Char('.')); + if (index > 0) { + extension = extension.mid(index + 1); + mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension); + } + } + + KURL url(m_reply->url()); + String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromAscii(m_reply->rawHeader("Content-Disposition"))); + + if (suggestedFilename.isEmpty()) + suggestedFilename = url.lastPathComponent(); + + ResourceResponse response(url, mimeType, + m_reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), + encoding, + suggestedFilename); + + const bool isLocalFileReply = (m_reply->url().scheme() == QLatin1String("file")); + int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + if (!isLocalFileReply) + response.setHTTPStatusCode(statusCode); + else if (m_reply->error() == QNetworkReply::ContentNotFoundError) + response.setHTTPStatusCode(404); + + + /* Fill in the other fields + * For local file requests remove the content length and the last-modified + * headers as required by fast/dom/xmlhttprequest-get.xhtml + */ + foreach (QByteArray headerName, m_reply->rawHeaderList()) { + + if (isLocalFileReply + && (headerName == "Content-Length" || headerName == "Last-Modified")) + continue; + + response.setHTTPHeaderField(QString::fromAscii(headerName), QString::fromAscii(m_reply->rawHeader(headerName))); + } + + if (isLocalFileReply) + response.setExpirationDate(m_startTime); + + QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if (redirection.isValid()) { + QUrl newUrl = m_reply->url().resolved(redirection); + ResourceRequest newRequest = m_resourceHandle->request(); + newRequest.setURL(newUrl); + + if (((statusCode >= 301 && statusCode <= 303) || statusCode == 307) && m_method == QNetworkAccessManager::PostOperation) { + m_method = QNetworkAccessManager::GetOperation; + newRequest.setHTTPMethod("GET"); + } + + client->willSendRequest(m_resourceHandle, newRequest, response); + m_redirected = true; + m_request = newRequest.toNetworkRequest(); + } else { + client->didReceiveResponse(m_resourceHandle, response); + } +} + +void QNetworkReplyHandler::forwardData() +{ + m_shouldForwardData = (m_loadMode == LoadDeferred); + if (m_loadMode == LoadDeferred) + return; + + sendResponseIfNeeded(); + + // don't emit the "Document has moved here" type of HTML + if (m_redirected) + return; + + if (!m_resourceHandle) + return; + + QByteArray data = m_reply->read(m_reply->bytesAvailable()); + + ResourceHandleClient* client = m_resourceHandle->client(); + if (!client) + return; + + if (!data.isEmpty()) + client->didReceiveData(m_resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/); +} + +void QNetworkReplyHandler::start() +{ + m_shouldStart = false; + + ResourceHandleInternal* d = m_resourceHandle->getInternal(); + + QNetworkAccessManager* manager = d->m_frame->page()->networkAccessManager(); + + const QUrl url = m_request.url(); + const QString scheme = url.scheme(); + // Post requests on files and data don't really make sense, but for + // fast/forms/form-post-urlencoded.html and for fast/forms/button-state-restore.html + // we still need to retrieve the file/data, which means we map it to a Get instead. + if (m_method == QNetworkAccessManager::PostOperation + && (!url.toLocalFile().isEmpty() || url.scheme() == QLatin1String("data"))) + m_method = QNetworkAccessManager::GetOperation; + + m_startTime = QDateTime::currentDateTime().toTime_t(); + + switch (m_method) { + case QNetworkAccessManager::GetOperation: + m_reply = manager->get(m_request); + break; + case QNetworkAccessManager::PostOperation: { + FormDataIODevice* postDevice = new FormDataIODevice(d->m_request.httpBody()); + m_reply = manager->post(m_request, postDevice); + postDevice->setParent(m_reply); + break; + } + case QNetworkAccessManager::HeadOperation: + m_reply = manager->head(m_request); + break; + case QNetworkAccessManager::PutOperation: { + FormDataIODevice* putDevice = new FormDataIODevice(d->m_request.httpBody()); + m_reply = manager->put(m_request, putDevice); + putDevice->setParent(m_reply); + break; + } + case QNetworkAccessManager::UnknownOperation: { + m_reply = 0; + ResourceHandleClient* client = m_resourceHandle->client(); + if (client) { + ResourceError error(url.host(), 400 /*bad request*/, + url.toString(), + QCoreApplication::translate("QWebPage", "Bad HTTP request")); + client->didFail(m_resourceHandle, error); + } + return; + } + } + + m_reply->setParent(this); + + connect(m_reply, SIGNAL(finished()), + this, SLOT(finish()), Qt::QueuedConnection); + + // For http(s) we know that the headers are complete upon metaDataChanged() emission, so we + // can send the response as early as possible + if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) + connect(m_reply, SIGNAL(metaDataChanged()), + this, SLOT(sendResponseIfNeeded()), Qt::QueuedConnection); + + connect(m_reply, SIGNAL(readyRead()), + this, SLOT(forwardData()), Qt::QueuedConnection); +} + +void QNetworkReplyHandler::resetState() +{ + m_redirected = false; + m_responseSent = false; + m_shouldStart = true; + m_shouldFinish = false; + m_shouldSendResponse = false; + m_shouldForwardData = false; +} + +void QNetworkReplyHandler::sendQueuedItems() +{ + Q_ASSERT(m_loadMode == LoadNormal); + + if (m_shouldStart) + start(); + + if (m_shouldSendResponse) + sendResponseIfNeeded(); + + if (m_shouldForwardData) + forwardData(); + + if (m_shouldFinish) + finish(); +} + +} + +#include "moc_QNetworkReplyHandler.cpp" + +#endif diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h new file mode 100644 index 0000000..98be28d --- /dev/null +++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h @@ -0,0 +1,118 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef QNETWORKREPLYHANDLER_H +#define QNETWORKREPLYHANDLER_H + +#include <QObject> + +#if QT_VERSION >= 0x040400 + +#include <QNetworkRequest> +#include <QNetworkAccessManager> + +#include "FormData.h" + +QT_BEGIN_NAMESPACE +class QFile; +class QNetworkReply; +QT_END_NAMESPACE + +namespace WebCore { + +class ResourceHandle; + +class QNetworkReplyHandler : public QObject +{ + Q_OBJECT +public: + enum LoadMode { + LoadNormal, + LoadDeferred + }; + + QNetworkReplyHandler(ResourceHandle *handle, LoadMode); + void setLoadMode(LoadMode); + + QNetworkReply* reply() const { return m_reply; } + + void abort(); + + QNetworkReply* release(); + +private slots: + void finish(); + void sendResponseIfNeeded(); + void forwardData(); + +private: + void start(); + void resetState(); + void sendQueuedItems(); + + QNetworkReply* m_reply; + ResourceHandle* m_resourceHandle; + bool m_redirected; + bool m_responseSent; + LoadMode m_loadMode; + QNetworkAccessManager::Operation m_method; + QNetworkRequest m_request; + uint m_startTime; + + // defer state holding + bool m_shouldStart; + bool m_shouldFinish; + bool m_shouldSendResponse; + bool m_shouldForwardData; +}; + +// Self destructing QIODevice for FormData +// For QNetworkAccessManager::put we will have to gurantee that the +// QIODevice is valid as long finished() of the QNetworkReply has not +// been emitted. With the presence of QNetworkReplyHandler::release I do +// not want to gurantee this. +class FormDataIODevice : public QIODevice { + Q_OBJECT +public: + FormDataIODevice(FormData*); + ~FormDataIODevice(); + + void setParent(QNetworkReply*); + bool isSequential() const; + +protected: + qint64 readData(char*, qint64); + qint64 writeData(const char*, qint64); + +private Q_SLOTS: + void slotFinished(); + +private: + void moveToNextElement(); + +private: + Vector<FormDataElement> m_formElements; + QFile* m_currentFile; + qint64 m_currentDelta; +}; + +} + +#endif + +#endif // QNETWORKREPLYHANDLER_H diff --git a/WebCore/platform/network/qt/ResourceError.h b/WebCore/platform/network/qt/ResourceError.h new file mode 100644 index 0000000..ca8d36b --- /dev/null +++ b/WebCore/platform/network/qt/ResourceError.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceError_h +#define ResourceError_h + +#include "ResourceErrorBase.h" + +namespace WebCore { + +class ResourceError : public ResourceErrorBase +{ +public: + ResourceError() + { + } + + ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) + { + } +}; + +} + +#endif // ResourceError_h_ diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp new file mode 100644 index 0000000..7af5895 --- /dev/null +++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008 Holger Hans Peter Freyther + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "Frame.h" +#include "DocLoader.h" +#include "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "qwebpage_p.h" +#include "ChromeClientQt.h" +#include "FrameLoaderClientQt.h" +#include "Page.h" +#include "QNetworkReplyHandler.h" + +#include "NotImplemented.h" + +#include <QCoreApplication> +#include <QUrl> +#if QT_VERSION >= 0x040400 +#include <QNetworkAccessManager> +#include <QNetworkRequest> +#include <QNetworkReply> +#else +#include "qwebnetworkinterface_p.h" +#endif + +namespace WebCore { + +class WebCoreSynchronousLoader : public ResourceHandleClient { +public: + WebCoreSynchronousLoader(); + + void waitForCompletion(); + + virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&); + virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived); + virtual void didFinishLoading(ResourceHandle*); + virtual void didFail(ResourceHandle*, const ResourceError&); + + ResourceResponse resourceResponse() const { return m_response; } + ResourceError resourceError() const { return m_error; } + Vector<char> data() const { return m_data; } + +private: + ResourceResponse m_response; + ResourceError m_error; + Vector<char> m_data; + bool m_finished; +}; + +WebCoreSynchronousLoader::WebCoreSynchronousLoader() + : m_finished(false) +{ +} + +void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response) +{ + m_response = response; +} + +void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int) +{ + m_data.append(data, length); +} + +void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*) +{ + m_finished = true; +} + +void WebCoreSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error) +{ + m_error = error; + m_finished = true; +} + +void WebCoreSynchronousLoader::waitForCompletion() +{ + while (!m_finished) + QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); +} + +ResourceHandleInternal::~ResourceHandleInternal() +{ +} + +ResourceHandle::~ResourceHandle() +{ + if (d->m_job) + cancel(); +} + +bool ResourceHandle::start(Frame* frame) +{ + if (!frame) + return false; + + Page *page = frame->page(); + // If we are no longer attached to a Page, this must be an attempted load from an + // onUnload handler, so let's just block it. + if (!page) + return false; + + 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() +{ + return false; +} + +bool ResourceHandle::willLoadFromCache(ResourceRequest& request) +{ + notImplemented(); + return false; +} + +bool ResourceHandle::supportsBufferedData() +{ + return false; +} + +PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() +{ + ASSERT_NOT_REACHED(); + return 0; +} + +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame) +{ + 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(); + d->m_frame = static_cast<FrameLoaderClientQt*>(frame->loader()->client())->webFrame(); + d->m_job = new QNetworkReplyHandler(&handle, QNetworkReplyHandler::LoadNormal); +#endif + + syncLoader.waitForCompletion(); + error = syncLoader.resourceError(); + data = syncLoader.data(); + response = syncLoader.resourceResponse(); +} + + +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 new file mode 100644 index 0000000..af76f61 --- /dev/null +++ b/WebCore/platform/network/qt/ResourceRequest.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequest_h +#define ResourceRequest_h + +#include "ResourceRequestBase.h" + +QT_BEGIN_NAMESPACE +class QNetworkRequest; +QT_END_NAMESPACE + +namespace WebCore { + + struct ResourceRequest : ResourceRequestBase { + + ResourceRequest(const String& url) + : ResourceRequestBase(KURL(url), UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url) + : ResourceRequestBase(url, UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy) + : ResourceRequestBase(url, policy) + { + setHTTPReferrer(referrer); + } + + ResourceRequest() + : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + { + } + +#if QT_VERSION >= 0x040400 + QNetworkRequest toNetworkRequest() const; +#endif + + private: + friend class ResourceRequestBase; + + void doUpdatePlatformRequest() {} + void doUpdateResourceRequest() {} + }; + +} // namespace WebCore + +#endif // ResourceRequest_h diff --git a/WebCore/platform/network/qt/ResourceRequestQt.cpp b/WebCore/platform/network/qt/ResourceRequestQt.cpp new file mode 100644 index 0000000..9308878 --- /dev/null +++ b/WebCore/platform/network/qt/ResourceRequestQt.cpp @@ -0,0 +1,49 @@ +/* + Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "ResourceRequest.h" + +#include <qglobal.h> +#if QT_VERSION >= 0x040400 + +#include <QNetworkRequest> +#include <QUrl> + +namespace WebCore { + +QNetworkRequest ResourceRequest::toNetworkRequest() const +{ + QNetworkRequest request; + request.setUrl(url()); + + 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); + } + + return request; +} + +} + +#endif diff --git a/WebCore/platform/network/qt/ResourceResponse.h b/WebCore/platform/network/qt/ResourceResponse.h new file mode 100644 index 0000000..345ef25 --- /dev/null +++ b/WebCore/platform/network/qt/ResourceResponse.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponse_h +#define ResourceResponse_h + +#include "ResourceResponseBase.h" + +namespace WebCore { + +class ResourceResponse : public ResourceResponseBase { +public: + ResourceResponse() + { + } + + ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename) + : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename) + { + } +}; + +} // namespace WebCore + +#endif // ResourceResponse_h diff --git a/WebCore/platform/network/soup/AuthenticationChallenge.h b/WebCore/platform/network/soup/AuthenticationChallenge.h new file mode 100644 index 0000000..5177f1e --- /dev/null +++ b/WebCore/platform/network/soup/AuthenticationChallenge.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 AuthenticationChallenge_h +#define AuthenticationChallenge_h + +#include "AuthenticationChallengeBase.h" + +namespace WebCore { + +class AuthenticationChallenge : public AuthenticationChallengeBase { +public: + AuthenticationChallenge() + { + } + + AuthenticationChallenge(const ProtectionSpace& protectionSpace, const Credential& proposedCredential, unsigned previousFailureCount, const ResourceResponse& response, const ResourceError& error) + : AuthenticationChallengeBase(protectionSpace, proposedCredential, previousFailureCount, response, error) + { + } +}; + +} + +#endif diff --git a/WebCore/platform/network/soup/CookieJarSoup.cpp b/WebCore/platform/network/soup/CookieJarSoup.cpp new file mode 100644 index 0000000..4ae90e5 --- /dev/null +++ b/WebCore/platform/network/soup/CookieJarSoup.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2008 Xan Lopez <xan@gnome.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "CString.h" +#include "CookieJar.h" + +#include "KURL.h" +#include "PlatformString.h" +#include "StringHash.h" + +#include <libsoup/soup.h> + +namespace WebCore { + +SoupCookieJar* getCookieJar() +{ + static SoupCookieJar* jar = NULL; + + if (!jar) + jar = soup_cookie_jar_new(); + + return jar; +} + +void setCookies(Document* /*document*/, const KURL& url, const KURL& /*policyURL*/, const String& value) +{ + SoupCookieJar* jar = getCookieJar(); + if (!jar) + return; + + SoupURI* origin = soup_uri_new(url.string().utf8().data()); + + soup_cookie_jar_set_cookie(jar, origin, value.utf8().data()); + soup_uri_free(origin); +} + +String cookies(const Document* /*document*/, const KURL& url) +{ + SoupCookieJar* jar = getCookieJar(); + if (!jar) + return String(); + + SoupURI* uri = soup_uri_new(url.string().utf8().data()); + char* cookies = soup_cookie_jar_get_cookies(jar, uri, FALSE); + soup_uri_free(uri); + + String result(cookies); + g_free(cookies); + + return result; +} + +bool cookiesEnabled(const Document* /*document*/) +{ + return getCookieJar(); +} + +} diff --git a/WebCore/platform/network/soup/DNSSoup.cpp b/WebCore/platform/network/soup/DNSSoup.cpp new file mode 100644 index 0000000..1ffe1a0 --- /dev/null +++ b/WebCore/platform/network/soup/DNSSoup.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008 Apple Computer, 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 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 COMPUTER, INC. OR + * 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 "DNS.h" + +#include "NotImplemented.h" + +namespace WebCore { + +void prefetchDNS(const String& hostname) +{ + notImplemented(); +} + +} diff --git a/WebCore/platform/network/soup/ResourceError.h b/WebCore/platform/network/soup/ResourceError.h new file mode 100644 index 0000000..2d11367 --- /dev/null +++ b/WebCore/platform/network/soup/ResourceError.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceError_h +#define ResourceError_h + +#include "ResourceErrorBase.h" + +namespace WebCore { + +class ResourceError : public ResourceErrorBase +{ +public: + ResourceError() + { + } + + ResourceError(const String& domain, int errorCode, const String& failingURL, const String& localizedDescription) + : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription) + { + } +}; + +} + +#endif // ResourceError_h_ diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp new file mode 100644 index 0000000..d48ce27 --- /dev/null +++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp @@ -0,0 +1,591 @@ +/* + * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) 2008 Xan Lopez <xan@gnome.org> + * Copyright (C) 2008 Collabora Ltd. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include "CString.h" +#include "ResourceHandle.h" + +#include "Base64.h" +#include "CookieJar.h" +#include "DocLoader.h" +#include "Frame.h" +#include "HTTPParsers.h" +#include "MIMETypeRegistry.h" +#include "NotImplemented.h" +#include "ResourceError.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "ResourceResponse.h" +#include "TextEncoding.h" + +#include <gio/gio.h> +#include <libsoup/soup.h> +#include <libsoup/soup-message.h> + +#if PLATFORM(GTK) + #if GLIB_CHECK_VERSION(2,12,0) + #define USE_GLIB_BASE64 + #endif +#endif + +namespace WebCore { + +static SoupSession* session = 0; + +enum +{ + ERROR_TRANSPORT, + ERROR_UNKNOWN_PROTOCOL, + ERROR_BAD_NON_HTTP_METHOD +}; + +ResourceHandleInternal::~ResourceHandleInternal() +{ + if (m_msg) { + g_object_unref(m_msg); + m_msg = 0; + } +} + +ResourceHandle::~ResourceHandle() +{ +} + +static void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response) +{ + SoupMessageHeadersIter iter; + const char* name = NULL; + const char* value = NULL; + soup_message_headers_iter_init(&iter, msg->response_headers); + while (soup_message_headers_iter_next(&iter, &name, &value)) + response->setHTTPHeaderField(name, value); + + String contentType = soup_message_headers_get(msg->response_headers, "Content-Type"); + char* uri = soup_uri_to_string(soup_message_get_uri(msg), FALSE); + response->setUrl(KURL(uri)); + g_free(uri); + response->setMimeType(extractMIMETypeFromMediaType(contentType)); + response->setTextEncodingName(extractCharsetFromMediaType(contentType)); + response->setExpectedContentLength(soup_message_headers_get_content_length(msg->response_headers)); + response->setHTTPStatusCode(msg->status_code); + response->setSuggestedFilename(filenameFromHTTPContentDisposition(response->httpHeaderField("Content-Disposition"))); +} + +// Called each time the message is going to be sent again except the first time. +// It's used mostly to let webkit know about redirects. +static void restartedCallback(SoupMessage* msg, gpointer data) +{ + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + if (!handle) + return; + ResourceHandleInternal* d = handle->getInternal(); + if (d->m_cancelled) + return; + + char* uri = soup_uri_to_string(soup_message_get_uri(msg), FALSE); + String location = String(uri); + g_free(uri); + KURL newURL = KURL(handle->request().url(), location); + + ResourceRequest request = handle->request(); + ResourceResponse response; + request.setURL(newURL); + fillResponseFromMessage(msg, &response); + if (d->client()) + d->client()->willSendRequest(handle, request, response); + + d->m_request.setURL(newURL); +} + +static void gotHeadersCallback(SoupMessage* msg, gpointer data) +{ + if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) + return; + + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + if (!handle) + return; + ResourceHandleInternal* d = handle->getInternal(); + if (d->m_cancelled) + return; + ResourceHandleClient* client = handle->client(); + if (!client) + return; + + fillResponseFromMessage(msg, &d->m_response); + client->didReceiveResponse(handle, d->m_response); + soup_message_set_flags(msg, SOUP_MESSAGE_OVERWRITE_CHUNKS); +} + +static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data) +{ + if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) + return; + + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + if (!handle) + return; + ResourceHandleInternal* d = handle->getInternal(); + if (d->m_cancelled) + return; + ResourceHandleClient* client = handle->client(); + if (!client) + return; + + client->didReceiveData(handle, chunk->data, chunk->length, false); +} + +// Called at the end of the message, with all the necessary about the last informations. +// Doesn't get called for redirects. +static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer data) +{ + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + // TODO: maybe we should run this code even if there's no client? + if (!handle) + return; + + ResourceHandleInternal* d = handle->getInternal(); + // The message has been handled. + d->m_msg = NULL; + + ResourceHandleClient* client = handle->client(); + if (!client) + return; + + if (d->m_cancelled) + return; + + if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) { + char* uri = soup_uri_to_string(soup_message_get_uri(msg), FALSE); + ResourceError error("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(msg->reason_phrase)); + g_free(uri); + client->didFail(handle, error); + return; + } else if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) { + fillResponseFromMessage(msg, &d->m_response); + client->didReceiveResponse(handle, d->m_response); + + // WebCore might have cancelled the job in the while + if (d->m_cancelled) + return; + + if (msg->response_body->data) + client->didReceiveData(handle, msg->response_body->data, msg->response_body->length, true); + } + + client->didFinishLoading(handle); +} + +// parseDataUrl() is taken from the CURL http backend. +static gboolean parseDataUrl(gpointer callback_data) +{ + ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data); + ResourceHandleClient* client = handle->client(); + + ASSERT(client); + if (!client) + return FALSE; + + String url = handle->request().url().string(); + ASSERT(url.startsWith("data:", false)); + + int index = url.find(','); + if (index == -1) { + client->cannotShowURL(handle); + return FALSE; + } + + String mediaType = url.substring(5, index - 5); + String data = url.substring(index + 1); + + bool base64 = mediaType.endsWith(";base64", false); + if (base64) + mediaType = mediaType.left(mediaType.length() - 7); + + if (mediaType.isEmpty()) + mediaType = "text/plain;charset=US-ASCII"; + + String mimeType = extractMIMETypeFromMediaType(mediaType); + String charset = extractCharsetFromMediaType(mediaType); + + ResourceResponse response; + response.setMimeType(mimeType); + + if (base64) { + data = decodeURLEscapeSequences(data); + response.setTextEncodingName(charset); + client->didReceiveResponse(handle, response); + + // Use the GLib Base64 if available, since WebCore's decoder isn't + // general-purpose and fails on Acid3 test 97 (whitespace). +#ifdef USE_GLIB_BASE64 + size_t outLength = 0; + char* outData = 0; + outData = reinterpret_cast<char*>(g_base64_decode(data.utf8().data(), &outLength)); + if (outData && outLength > 0) + client->didReceiveData(handle, outData, outLength, 0); + g_free(outData); +#else + Vector<char> out; + if (base64Decode(data.latin1().data(), data.latin1().length(), out) && out.size() > 0) + client->didReceiveData(handle, out.data(), out.size(), 0); +#endif + } else { + // We have to convert to UTF-16 early due to limitations in KURL + data = decodeURLEscapeSequences(data, TextEncoding(charset)); + response.setTextEncodingName("UTF-16"); + client->didReceiveResponse(handle, response); + if (data.length() > 0) + client->didReceiveData(handle, reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0); + } + + client->didFinishLoading(handle); + + return FALSE; +} + +bool ResourceHandle::startData(String urlString) +{ + // If parseDataUrl is called synchronously the job is not yet effectively started + // and webkit won't never know that the data has been parsed even didFinishLoading is called. + g_idle_add(parseDataUrl, this); + return true; +} + +bool ResourceHandle::startHttp(String urlString) +{ + if (!session) { + session = soup_session_async_new(); + + soup_session_add_feature(session, SOUP_SESSION_FEATURE(getCookieJar())); + + const char* soup_debug = g_getenv("WEBKIT_SOUP_LOGGING"); + if (soup_debug) { + int soup_debug_level = atoi(soup_debug); + + SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(soup_debug_level), -1); + soup_logger_attach(logger, session); + g_object_unref(logger); + } + } + + SoupMessage* msg; + msg = soup_message_new(request().httpMethod().utf8().data(), urlString.utf8().data()); + g_signal_connect(msg, "restarted", G_CALLBACK(restartedCallback), this); + + g_signal_connect(msg, "got-headers", G_CALLBACK(gotHeadersCallback), this); + g_signal_connect(msg, "got-chunk", G_CALLBACK(gotChunkCallback), this); + + HTTPHeaderMap customHeaders = d->m_request.httpHeaderFields(); + if (!customHeaders.isEmpty()) { + HTTPHeaderMap::const_iterator end = customHeaders.end(); + for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) + soup_message_headers_append(msg->request_headers, it->first.utf8().data(), it->second.utf8().data()); + } + + FormData* httpBody = d->m_request.httpBody(); + if (httpBody && !httpBody->isEmpty()) { + // Making a copy of the request body isn't the most efficient way to + // serialize it, but by far the most simple. Dealing with individual + // FormData elements and shared buffers should be more memory + // efficient. + // + // This possibly isn't handling file uploads/attachments, for which + // shared buffers or streaming should definitely be used. + Vector<char> body; + httpBody->flatten(body); + soup_message_set_request(msg, d->m_request.httpContentType().utf8().data(), + SOUP_MEMORY_COPY, body.data(), body.size()); + } + + d->m_msg = static_cast<SoupMessage*>(g_object_ref(msg)); + soup_session_queue_message(session, d->m_msg, finishedCallback, this); + + return true; +} + +bool ResourceHandle::start(Frame* frame) +{ + ASSERT(!d->m_msg); + + // If we are no longer attached to a Page, this must be an attempted load from an + // onUnload handler, so let's just block it. + if (!frame->page()) + return false; + + KURL url = request().url(); + String urlString = url.string(); + String protocol = url.protocol(); + + if (equalIgnoringCase(protocol, "data")) + return startData(urlString); + else if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) + return startHttp(urlString); + else if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps")) + // FIXME: should we be doing any other protocols here? + return startGio(urlString); + else { + // If we don't call didFail the job is not complete for webkit even false is returned. + if (d->client()) { + ResourceError error("webkit-network-error", ERROR_UNKNOWN_PROTOCOL, urlString, protocol); + d->client()->didFail(this, error); + } + return false; + } +} + +void ResourceHandle::cancel() +{ + d->m_cancelled = true; + if (d->m_msg) { + soup_session_cancel_message(session, d->m_msg, SOUP_STATUS_CANCELLED); + // For re-entrancy troubles we call didFinishLoading when the message hasn't been handled yet. + d->client()->didFinishLoading(this); + } else if (d->m_cancellable) { + g_cancellable_cancel(d->m_cancellable); + d->client()->didFinishLoading(this); + } +} + +PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() +{ + ASSERT_NOT_REACHED(); + return 0; +} + +bool ResourceHandle::supportsBufferedData() +{ + return false; +} + +void ResourceHandle::setDefersLoading(bool defers) +{ + d->m_defersLoading = defers; + notImplemented(); +} + +bool ResourceHandle::loadsBlocked() +{ + return false; +} + +bool ResourceHandle::willLoadFromCache(ResourceRequest&) +{ + // Not having this function means that we'll ask the user about re-posting a form + // even when we go back to a page that's still in the cache. + notImplemented(); + return false; +} + +void ResourceHandle::loadResourceSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>&, Frame*) +{ + notImplemented(); +} + +// GIO-based loader + +static inline ResourceError networkErrorForFile(GFile* file, GError* error) +{ + // FIXME: Map gio errors to a more detailed error code when we have it in WebKit. + gchar* uri = g_file_get_uri(file); + ResourceError resourceError("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(error->message)); + g_free(uri); + return resourceError; +} + +static void cleanupGioOperation(ResourceHandle* handle) +{ + ResourceHandleInternal* d = handle->getInternal(); + + if (d->m_gfile) { + g_object_unref(d->m_gfile); + d->m_gfile = NULL; + } + if (d->m_cancellable) { + g_object_unref(d->m_cancellable); + d->m_cancellable = NULL; + } + if (d->m_input_stream) { + g_object_unref(d->m_input_stream); + d->m_input_stream = NULL; + } + if (d->m_buffer) { + g_free(d->m_buffer); + d->m_buffer = NULL; + } +} + +static void closeCallback(GObject* source, GAsyncResult* res, gpointer data) +{ + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + ResourceHandleInternal* d = handle->getInternal(); + ResourceHandleClient* client = handle->client(); + + g_input_stream_close_finish(d->m_input_stream, res, NULL); + cleanupGioOperation(handle); + client->didFinishLoading(handle); +} + +static void readCallback(GObject* source, GAsyncResult* res, gpointer data) +{ + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + ResourceHandleInternal* d = handle->getInternal(); + ResourceHandleClient* client = handle->client(); + + if (d->m_cancelled || !client) { + cleanupGioOperation(handle); + return; + } + + gssize nread; + GError *error = 0; + + nread = g_input_stream_read_finish(d->m_input_stream, res, &error); + if (error) { + client->didFail(handle, networkErrorForFile(d->m_gfile, error)); + cleanupGioOperation(handle); + return; + } else if (!nread) { + g_input_stream_close_async(d->m_input_stream, G_PRIORITY_DEFAULT, + NULL, closeCallback, handle); + return; + } + + d->m_total += nread; + client->didReceiveData(handle, d->m_buffer, nread, d->m_total); + + g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, + G_PRIORITY_DEFAULT, d->m_cancellable, + readCallback, handle); +} + +static void openCallback(GObject* source, GAsyncResult* res, gpointer data) +{ + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + ResourceHandleInternal* d = handle->getInternal(); + ResourceHandleClient* client = handle->client(); + + if (d->m_cancelled || !client) { + cleanupGioOperation(handle); + return; + } + + GFileInputStream* in; + GError *error = NULL; + in = g_file_read_finish(G_FILE(source), res, &error); + if (error) { + client->didFail(handle, networkErrorForFile(d->m_gfile, error)); + cleanupGioOperation(handle); + return; + } + + d->m_input_stream = G_INPUT_STREAM(in); + d->m_bufsize = 8192; + d->m_buffer = static_cast<char*>(g_malloc(d->m_bufsize)); + d->m_total = 0; + g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize, + G_PRIORITY_DEFAULT, d->m_cancellable, + readCallback, handle); +} + +static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer data) +{ + ResourceHandle* handle = static_cast<ResourceHandle*>(data); + ResourceHandleInternal* d = handle->getInternal(); + ResourceHandleClient* client = handle->client(); + + if (d->m_cancelled) { + cleanupGioOperation(handle); + return; + } + + ResourceResponse response; + + char* uri = g_file_get_uri(d->m_gfile); + response.setUrl(KURL(uri)); + g_free(uri); + + GError *error = NULL; + GFileInfo* info = g_file_query_info_finish(d->m_gfile, res, &error); + + if (error) { + // FIXME: to be able to handle ftp URIs properly, we must + // check if the error is G_IO_ERROR_NOT_MOUNTED, and if so, + // call g_file_mount_enclosing_volume() to mount the ftp + // server (and then keep track of the fact that we mounted it, + // and set a timeout to unmount it later after it's been idle + // for a while). + + client->didFail(handle, networkErrorForFile(d->m_gfile, error)); + cleanupGioOperation(handle); + return; + } + + if (g_file_info_get_file_type(info) != G_FILE_TYPE_REGULAR) { + // FIXME: what if the URI points to a directory? Should we + // generate a listing? How? What do other backends do here? + + client->didFail(handle, networkErrorForFile(d->m_gfile, error)); + cleanupGioOperation(handle); + return; + } + + response.setMimeType(g_file_info_get_content_type(info)); + response.setExpectedContentLength(g_file_info_get_size(info)); + response.setHTTPStatusCode(SOUP_STATUS_OK); + + GTimeVal tv; + g_file_info_get_modification_time(info, &tv); + response.setLastModifiedDate(tv.tv_sec); + + client->didReceiveResponse(handle, response); + + g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable, + openCallback, handle); +} + +bool ResourceHandle::startGio(String urlString) +{ + if (request().httpMethod() != "GET") { + ResourceError error("webkit-network-error", ERROR_BAD_NON_HTTP_METHOD, urlString, request().httpMethod()); + d->client()->didFail(this, error); + return false; + } + + // Remove the fragment part of the URL since the file backend doesn't deal with it + int fragPos; + if ((fragPos = urlString.find("#")) != -1) + urlString = urlString.left(fragPos); + + d->m_gfile = g_file_new_for_uri(urlString.utf8().data()); + d->m_cancellable = g_cancellable_new(); + g_file_query_info_async(d->m_gfile, + G_FILE_ATTRIBUTE_STANDARD_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," + G_FILE_ATTRIBUTE_STANDARD_SIZE, + G_FILE_QUERY_INFO_NONE, + G_PRIORITY_DEFAULT, d->m_cancellable, + queryInfoCallback, this); + return true; +} + +} + diff --git a/WebCore/platform/network/soup/ResourceRequest.h b/WebCore/platform/network/soup/ResourceRequest.h new file mode 100644 index 0000000..efb1240 --- /dev/null +++ b/WebCore/platform/network/soup/ResourceRequest.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2003, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceRequest_h +#define ResourceRequest_h + +#include "ResourceRequestBase.h" + +namespace WebCore { + + struct ResourceRequest : ResourceRequestBase { + + ResourceRequest(const String& url) + : ResourceRequestBase(KURL(url), UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url) + : ResourceRequestBase(url, UseProtocolCachePolicy) + { + } + + ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy) + : ResourceRequestBase(url, policy) + { + setHTTPReferrer(referrer); + } + + ResourceRequest() + : ResourceRequestBase(KURL(), UseProtocolCachePolicy) + { + } + + private: + friend class ResourceRequestBase; + + void doUpdatePlatformRequest() {} + void doUpdateResourceRequest() {} + }; + +} // namespace WebCore + +#endif // ResourceRequest_h diff --git a/WebCore/platform/network/soup/ResourceResponse.h b/WebCore/platform/network/soup/ResourceResponse.h new file mode 100644 index 0000000..b8cb586 --- /dev/null +++ b/WebCore/platform/network/soup/ResourceResponse.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceResponse_h +#define ResourceResponse_h + +#include "ResourceResponseBase.h" + +namespace WebCore { + +class ResourceResponse : public ResourceResponseBase { +public: + ResourceResponse() + : ResourceResponseBase() + { + } + + ResourceResponse(const KURL& url, const String& mimeType, long long expectedLength, const String& textEncodingName, const String& filename) + : ResourceResponseBase(url, mimeType, expectedLength, textEncodingName, filename) + { + } + +private: + friend class ResourceResponseBase; + + void doUpdateResourceResponse() + { + } +}; + +} // namespace WebCore + +#endif // ResourceResponse_h diff --git a/WebCore/platform/network/win/CookieJarCFNetWin.cpp b/WebCore/platform/network/win/CookieJarCFNetWin.cpp new file mode 100644 index 0000000..fd795ee --- /dev/null +++ b/WebCore/platform/network/win/CookieJarCFNetWin.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2006, 2007, 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "CookieJar.h" + +#include "CookieStorageWin.h" +#include "KURL.h" +#include "PlatformString.h" +#include "Document.h" +#include "ResourceHandle.h" +#include <windows.h> +#include <CoreFoundation/CoreFoundation.h> +#include <CFNetwork/CFHTTPCookiesPriv.h> +#include <WebKitSystemInterface/WebKitSystemInterface.h> + +namespace WebCore { + +static const CFStringRef s_setCookieKeyCF = CFSTR("Set-Cookie"); +static const CFStringRef s_cookieCF = CFSTR("Cookie"); + +void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL, const String& value) +{ + // <rdar://problem/5632883> CFHTTPCookieStorage happily stores an empty cookie, which would be sent as "Cookie: =". + if (value.isEmpty()) + return; + + CFHTTPCookieStorageRef cookieStorage = currentCookieStorage(); + if (!cookieStorage) + return; + + RetainPtr<CFURLRef> urlCF(AdoptCF, url.createCFURL()); + RetainPtr<CFURLRef> policyURLCF(AdoptCF, policyURL.createCFURL()); + + // <http://bugs.webkit.org/show_bug.cgi?id=6531>, <rdar://4409034> + // cookiesWithResponseHeaderFields doesn't parse cookies without a value + String cookieString = value.contains('=') ? value : value + "="; + + RetainPtr<CFStringRef> cookieStringCF(AdoptCF, cookieString.createCFString()); + RetainPtr<CFDictionaryRef> headerFieldsCF(AdoptCF, CFDictionaryCreate(kCFAllocatorDefault, (const void**)&s_setCookieKeyCF, + (const void**)&cookieStringCF, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); + + RetainPtr<CFArrayRef> cookiesCF(AdoptCF, CFHTTPCookieCreateWithResponseHeaderFields(kCFAllocatorDefault, + headerFieldsCF.get(), urlCF.get())); + + CFHTTPCookieStorageSetCookies(cookieStorage, cookiesCF.get(), urlCF.get(), policyURLCF.get()); +} + +String cookies(const Document* /*document*/, const KURL& url) +{ + CFHTTPCookieStorageRef cookieStorage = currentCookieStorage(); + if (!cookieStorage) + return String(); + + String cookieString; + RetainPtr<CFURLRef> urlCF(AdoptCF, url.createCFURL()); + + bool secure = equalIgnoringCase(url.protocol(), "https"); + + RetainPtr<CFArrayRef> cookiesCF(AdoptCF, CFHTTPCookieStorageCopyCookiesForURL(cookieStorage, urlCF.get(), secure)); + + // <rdar://problem/5632883> CFHTTPCookieStorage happily stores an empty cookie, which would be sent as "Cookie: =". + // We have a workaround in setCookies() to prevent that, but we also need to avoid sending cookies that were previously stored. + CFIndex count = CFArrayGetCount(cookiesCF.get()); + RetainPtr<CFMutableArrayRef> cookiesForURLFilteredCopy(AdoptCF, CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks)); + for (CFIndex i = 0; i < count; ++i) { + CFHTTPCookieRef cookie = (CFHTTPCookieRef)CFArrayGetValueAtIndex(cookiesCF.get(), i); + if (CFStringGetLength(CFHTTPCookieGetName(cookie)) != 0) + CFArrayAppendValue(cookiesForURLFilteredCopy.get(), cookie); + } + RetainPtr<CFDictionaryRef> headerCF(AdoptCF, CFHTTPCookieCopyRequestHeaderFields(kCFAllocatorDefault, cookiesForURLFilteredCopy.get())); + + return (CFStringRef)CFDictionaryGetValue(headerCF.get(), s_cookieCF); +} + +bool cookiesEnabled(const Document* /*document*/) +{ + CFHTTPCookieStorageAcceptPolicy policy = CFHTTPCookieStorageAcceptPolicyOnlyFromMainDocumentDomain; + if (CFHTTPCookieStorageRef cookieStorage = currentCookieStorage()) + policy = CFHTTPCookieStorageGetCookieAcceptPolicy(cookieStorage); + return policy == CFHTTPCookieStorageAcceptPolicyOnlyFromMainDocumentDomain || policy == CFHTTPCookieStorageAcceptPolicyAlways; +} + +} diff --git a/WebCore/platform/network/win/CookieJarWin.cpp b/WebCore/platform/network/win/CookieJarWin.cpp new file mode 100644 index 0000000..cdafb1b --- /dev/null +++ b/WebCore/platform/network/win/CookieJarWin.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2006, 2007, 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "CookieJar.h" + +#include "KURL.h" +#include "PlatformString.h" +#include "Document.h" +#include "ResourceHandle.h" +#include <windows.h> +#include <Wininet.h> + +namespace WebCore { + + +void setCookies(Document* /*document*/, const KURL& url, const KURL& policyURL, const String& value) +{ + // FIXME: Deal with the policy URL. + String str = url.string(); + String val = value; + InternetSetCookie(str.charactersWithNullTermination(), 0, val.charactersWithNullTermination()); +} + +String cookies(const Document* /*document*/, const KURL& url) +{ + String str = url.string(); + + DWORD count = str.length() + 1; + InternetGetCookie(str.charactersWithNullTermination(), 0, 0, &count); + if (count <= 1) // Null terminator counts as 1. + return String(); + + Vector<UChar> buffer(count); + InternetGetCookie(str.charactersWithNullTermination(), 0, buffer.data(), &count); + buffer.shrink(count - 1); // Ignore the null terminator. + return String::adopt(buffer); +} + +bool cookiesEnabled(const Document* /*document*/) +{ + return true; +} + +} diff --git a/WebCore/platform/network/win/CookieStorageWin.cpp b/WebCore/platform/network/win/CookieStorageWin.cpp new file mode 100644 index 0000000..5e74c17 --- /dev/null +++ b/WebCore/platform/network/win/CookieStorageWin.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "CookieStorageWin.h" + +#include <CFNetwork/CFHTTPCookiesPriv.h> +#include <WebKitSystemInterface/WebKitSystemInterface.h> +#include <wtf/RetainPtr.h> + +namespace WebCore { + +static RetainPtr<CFHTTPCookieStorageRef> s_cookieStorage; + +CFHTTPCookieStorageRef currentCookieStorage() +{ + if (s_cookieStorage) + return s_cookieStorage.get(); + return wkGetDefaultHTTPCookieStorage(); +} + +void setCurrentCookieStorage(CFHTTPCookieStorageRef cookieStorage) +{ + s_cookieStorage = cookieStorage; +} + +} diff --git a/WebCore/platform/network/win/CookieStorageWin.h b/WebCore/platform/network/win/CookieStorageWin.h new file mode 100644 index 0000000..4350b72 --- /dev/null +++ b/WebCore/platform/network/win/CookieStorageWin.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 CookieStorageWin_h +#define CookieStorageWin_h + +typedef struct OpaqueCFHTTPCookieStorage* CFHTTPCookieStorageRef; + +namespace WebCore { + + CFHTTPCookieStorageRef currentCookieStorage(); + + void setCurrentCookieStorage(CFHTTPCookieStorageRef cookieStorage); + +} + +#endif // CookieStorageWin_h diff --git a/WebCore/platform/network/win/NetworkStateNotifierWin.cpp b/WebCore/platform/network/win/NetworkStateNotifierWin.cpp new file mode 100644 index 0000000..f8cbace --- /dev/null +++ b/WebCore/platform/network/win/NetworkStateNotifierWin.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008 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. ``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 + * 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 "NetworkStateNotifier.h" + +#include <wtf/MainThread.h> +#include <wtf/Vector.h> + +#include <winsock2.h> +#include <iphlpapi.h> + +namespace WebCore { + +void NetworkStateNotifier::updateState() +{ + // Assume that we're online until proven otherwise. + m_isOnLine = true; + + Vector<char> buffer; + DWORD size = 0; + + if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, 0, &size) != ERROR_BUFFER_OVERFLOW)
+ return;
+
+ buffer.resize(size);
+ PIP_ADAPTER_ADDRESSES addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(buffer.data());
+ + if (::GetAdaptersAddresses(AF_UNSPEC, 0, 0, addresses, &size) != ERROR_SUCCESS) { + // We couldn't determine whether we're online or not, so assume that we are. + return; + } + + for (; addresses; addresses = addresses->Next) {
+ if (addresses->IfType == MIB_IF_TYPE_LOOPBACK)
+ continue;
+
+ if (addresses->OperStatus != IfOperStatusUp)
+ continue;
+
+ // We found an interface that was up.
+ return;
+ } + + // We didn't find any valid interfaces, so we must be offline. + m_isOnLine = false; +} + +void NetworkStateNotifier::addressChanged() +{ + bool oldOnLine = m_isOnLine; + + updateState(); + + if (m_isOnLine == oldOnLine) + return; + + if (m_networkStateChangedFunction) + m_networkStateChangedFunction(); +} + +void NetworkStateNotifier::callAddressChanged(void* context) +{ + static_cast<NetworkStateNotifier*>(context)->addressChanged(); +} + +void CALLBACK NetworkStateNotifier::addrChangeCallback(void* context, BOOLEAN timedOut) +{ + callOnMainThread(callAddressChanged, context); +} + +void NetworkStateNotifier::registerForAddressChange() +{ + HANDLE handle; + ::NotifyAddrChange(&handle, &m_overlapped); +} + +NetworkStateNotifier::NetworkStateNotifier() + : m_isOnLine(false) +{ + updateState(); + + memset(&m_overlapped, 0, sizeof(m_overlapped)); + + m_overlapped.hEvent = ::CreateEvent(0, false, false, 0); + + ::RegisterWaitForSingleObject(&m_waitHandle, m_overlapped.hEvent, addrChangeCallback, this, INFINITE, 0); + + registerForAddressChange(); +} + +} diff --git a/WebCore/platform/network/win/ResourceHandleWin.cpp b/WebCore/platform/network/win/ResourceHandleWin.cpp new file mode 100644 index 0000000..337b752 --- /dev/null +++ b/WebCore/platform/network/win/ResourceHandleWin.cpp @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceHandleInternal.h" +#include "ResourceHandleWin.h" + +#include "CString.h" +#include "DocLoader.h" +#include "Document.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "Page.h" +#include "ResourceError.h" +#include "Timer.h" +#include <windows.h> +#include <wininet.h> + +namespace WebCore { + +static unsigned transferJobId = 0; +static HashMap<int, ResourceHandle*>* jobIdMap = 0; + +static HWND transferJobWindowHandle = 0; +const LPCWSTR kResourceHandleWindowClassName = L"ResourceHandleWindowClass"; + +// Message types for internal use (keep in sync with kMessageHandlers) +enum { + handleCreatedMessage = WM_USER, + requestRedirectedMessage, + requestCompleteMessage +}; + +typedef void (ResourceHandle:: *ResourceHandleEventHandler)(LPARAM); +static const ResourceHandleEventHandler messageHandlers[] = { + &ResourceHandle::onHandleCreated, + &ResourceHandle::onRequestRedirected, + &ResourceHandle::onRequestComplete +}; + +static int addToOutstandingJobs(ResourceHandle* job) +{ + if (!jobIdMap) + jobIdMap = new HashMap<int, ResourceHandle*>; + transferJobId++; + jobIdMap->set(transferJobId, job); + return transferJobId; +} + +static void removeFromOutstandingJobs(int jobId) +{ + if (!jobIdMap) + return; + jobIdMap->remove(jobId); +} + +static ResourceHandle* lookupResourceHandle(int jobId) +{ + if (!jobIdMap) + return 0; + return jobIdMap->get(jobId); +} + +static LRESULT CALLBACK ResourceHandleWndProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + if (message >= handleCreatedMessage) { + UINT index = message - handleCreatedMessage; + if (index < _countof(messageHandlers)) { + unsigned jobId = (unsigned) wParam; + ResourceHandle* job = lookupResourceHandle(jobId); + if (job) { + ASSERT(job->d->m_jobId == jobId); + ASSERT(job->d->m_threadId == GetCurrentThreadId()); + (job->*(messageHandlers[index]))(lParam); + } + return 0; + } + } + return DefWindowProc(hWnd, message, wParam, lParam); +} + +static void initializeOffScreenResourceHandleWindow() +{ + if (transferJobWindowHandle) + return; + + WNDCLASSEX wcex; + memset(&wcex, 0, sizeof(WNDCLASSEX)); + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.lpfnWndProc = ResourceHandleWndProc; + wcex.hInstance = Page::instanceHandle(); + wcex.lpszClassName = kResourceHandleWindowClassName; + RegisterClassEx(&wcex); + + transferJobWindowHandle = CreateWindow(kResourceHandleWindowClassName, 0, 0, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, + HWND_MESSAGE, 0, Page::instanceHandle(), 0); +} + +ResourceHandleInternal::~ResourceHandleInternal() +{ + if (m_fileHandle != INVALID_HANDLE_VALUE) + CloseHandle(m_fileHandle); +} + +ResourceHandle::~ResourceHandle() +{ + if (d->m_jobId) + removeFromOutstandingJobs(d->m_jobId); +} + +void ResourceHandle::onHandleCreated(LPARAM lParam) +{ + if (!d->m_resourceHandle) { + d->m_resourceHandle = HINTERNET(lParam); + if (d->status != 0) { + // We were canceled before Windows actually created a handle for us, close and delete now. + InternetCloseHandle(d->m_resourceHandle); + delete this; + return; + } + + if (method() == "POST") { + // FIXME: Too late to set referrer properly. + String urlStr = url().path(); + int fragmentIndex = urlStr.find('#'); + if (fragmentIndex != -1) + urlStr = urlStr.left(fragmentIndex); + static LPCSTR accept[2]={"*/*", NULL}; + HINTERNET urlHandle = HttpOpenRequestA(d->m_resourceHandle, + "POST", urlStr.latin1().data(), 0, 0, accept, + INTERNET_FLAG_KEEP_CONNECTION | + INTERNET_FLAG_FORMS_SUBMIT | + INTERNET_FLAG_RELOAD | + INTERNET_FLAG_NO_CACHE_WRITE | + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP, + (DWORD_PTR)d->m_jobId); + if (urlHandle == INVALID_HANDLE_VALUE) { + InternetCloseHandle(d->m_resourceHandle); + delete this; + } + } + } else if (!d->m_secondaryHandle) { + assert(method() == "POST"); + d->m_secondaryHandle = HINTERNET(lParam); + + // Need to actually send the request now. + String headers = "Content-Type: application/x-www-form-urlencoded\n"; + headers += "Referer: "; + headers += d->m_postReferrer; + headers += "\n"; + const CString& headersLatin1 = headers.latin1(); + String formData = postData()->flattenToString(); + INTERNET_BUFFERSA buffers; + memset(&buffers, 0, sizeof(buffers)); + buffers.dwStructSize = sizeof(INTERNET_BUFFERSA); + buffers.lpcszHeader = headersLatin1; + buffers.dwHeadersLength = headers.length(); + buffers.dwBufferTotal = formData.length(); + + d->m_bytesRemainingToWrite = formData.length(); + d->m_formDataString = (char*)malloc(formData.length()); + d->m_formDataLength = formData.length(); + strncpy(d->m_formDataString, formData.latin1(), formData.length()); + d->m_writing = true; + HttpSendRequestExA(d->m_secondaryHandle, &buffers, 0, 0, (DWORD_PTR)d->m_jobId); + // FIXME: add proper error handling + } +} + +void ResourceHandle::onRequestRedirected(LPARAM lParam) +{ + // If already canceled, then ignore this event. + if (d->status != 0) + return; + + ResourceRequest request((StringImpl*) lParam); + ResourceResponse redirectResponse; + client()->willSendRequest(this, request, redirectResponse); +} + +void ResourceHandle::onRequestComplete(LPARAM lParam) +{ + if (d->m_writing) { + DWORD bytesWritten; + InternetWriteFile(d->m_secondaryHandle, + d->m_formDataString + (d->m_formDataLength - d->m_bytesRemainingToWrite), + d->m_bytesRemainingToWrite, + &bytesWritten); + d->m_bytesRemainingToWrite -= bytesWritten; + if (!d->m_bytesRemainingToWrite) { + // End the request. + d->m_writing = false; + HttpEndRequest(d->m_secondaryHandle, 0, 0, (DWORD_PTR)d->m_jobId); + free(d->m_formDataString); + d->m_formDataString = 0; + } + return; + } + + HINTERNET handle = (method() == "POST") ? d->m_secondaryHandle : d->m_resourceHandle; + BOOL ok = FALSE; + + static const int bufferSize = 32768; + char buffer[bufferSize]; + INTERNET_BUFFERSA buffers; + buffers.dwStructSize = sizeof(INTERNET_BUFFERSA); + buffers.lpvBuffer = buffer; + buffers.dwBufferLength = bufferSize; + + bool receivedAnyData = false; + while ((ok = InternetReadFileExA(handle, &buffers, IRF_NO_WAIT, (DWORD_PTR)this)) && buffers.dwBufferLength) { + if (!hasReceivedResponse()) { + setHasReceivedResponse(); + ResourceResponse response; + client()->didReceiveResponse(this, response); + } + client()->didReceiveData(this, buffer, buffers.dwBufferLength, 0); + buffers.dwBufferLength = bufferSize; + } + + PlatformDataStruct platformData; + platformData.errorString = 0; + platformData.error = 0; + platformData.loaded = ok; + + if (!ok) { + int error = GetLastError(); + if (error == ERROR_IO_PENDING) + return; + DWORD errorStringChars = 0; + if (!InternetGetLastResponseInfo(&platformData.error, 0, &errorStringChars)) { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + platformData.errorString = new TCHAR[errorStringChars]; + InternetGetLastResponseInfo(&platformData.error, platformData.errorString, &errorStringChars); + } + } + _RPTF1(_CRT_WARN, "Load error: %i\n", error); + } + + if (d->m_secondaryHandle) + InternetCloseHandle(d->m_secondaryHandle); + InternetCloseHandle(d->m_resourceHandle); + + client()->didFinishLoading(this); + delete this; +} + +static void __stdcall transferJobStatusCallback(HINTERNET internetHandle, + DWORD_PTR jobId, + DWORD internetStatus, + LPVOID statusInformation, + DWORD statusInformationLength) +{ +#ifdef RESOURCE_LOADER_DEBUG + char buf[64]; + _snprintf(buf, sizeof(buf), "status-callback: status=%u, job=%p\n", + internetStatus, jobId); + OutputDebugStringA(buf); +#endif + + UINT msg; + LPARAM lParam; + + switch (internetStatus) { + case INTERNET_STATUS_HANDLE_CREATED: + // tell the main thread about the newly created handle + msg = handleCreatedMessage; + lParam = (LPARAM) LPINTERNET_ASYNC_RESULT(statusInformation)->dwResult; + break; + case INTERNET_STATUS_REQUEST_COMPLETE: +#ifdef RESOURCE_LOADER_DEBUG + _snprintf(buf, sizeof(buf), "request-complete: result=%p, error=%u\n", + LPINTERNET_ASYNC_RESULT(statusInformation)->dwResult, + LPINTERNET_ASYNC_RESULT(statusInformation)->dwError); + OutputDebugStringA(buf); +#endif + // tell the main thread that the request is done + msg = requestCompleteMessage; + lParam = 0; + break; + case INTERNET_STATUS_REDIRECT: + // tell the main thread to observe this redirect (FIXME: we probably + // need to block the redirect at this point so the application can + // decide whether or not to follow the redirect) + msg = requestRedirectedMessage; + lParam = (LPARAM) new StringImpl((const UChar*) statusInformation, + statusInformationLength); + break; + case INTERNET_STATUS_USER_INPUT_REQUIRED: + // FIXME: prompt the user if necessary + ResumeSuspendedDownload(internetHandle, 0); + case INTERNET_STATUS_STATE_CHANGE: + // may need to call ResumeSuspendedDownload here as well + default: + return; + } + + PostMessage(transferJobWindowHandle, msg, (WPARAM) jobId, lParam); +} + +bool ResourceHandle::start(Frame* frame) +{ + ref(); + if (url().isLocalFile()) { + String path = url().path(); + // windows does not enjoy a leading slash on paths + if (path[0] == '/') + path = path.substring(1); + // FIXME: This is wrong. Need to use wide version of this call. + d->m_fileHandle = CreateFileA(path.utf8().data(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + // FIXME: perhaps this error should be reported asynchronously for + // consistency. + if (d->m_fileHandle == INVALID_HANDLE_VALUE) { + delete this; + return false; + } + + d->m_fileLoadTimer.startOneShot(0.0); + return true; + } else { + static HINTERNET internetHandle = 0; + if (!internetHandle) { + String userAgentStr = frame->loader()->userAgent() + String("", 1); + LPCWSTR userAgent = reinterpret_cast<const WCHAR*>(userAgentStr.characters()); + // leak the Internet for now + internetHandle = InternetOpen(userAgent, INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, INTERNET_FLAG_ASYNC); + } + if (!internetHandle) { + delete this; + return false; + } + static INTERNET_STATUS_CALLBACK callbackHandle = + InternetSetStatusCallback(internetHandle, transferJobStatusCallback); + + initializeOffScreenResourceHandleWindow(); + d->m_jobId = addToOutstandingJobs(this); + + DWORD flags = + INTERNET_FLAG_KEEP_CONNECTION | + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP; + + // For form posting, we can't use InternetOpenURL. We have to use + // InternetConnect followed by HttpSendRequest. + HINTERNET urlHandle; + String referrer = frame->loader()->referrer(); + if (method() == "POST") { + d->m_postReferrer = referrer; + String host = url().host(); + urlHandle = InternetConnectA(internetHandle, host.latin1().data(), + url().port(), + NULL, // no username + NULL, // no password + INTERNET_SERVICE_HTTP, + flags, (DWORD_PTR)d->m_jobId); + } else { + String urlStr = url().string(); + int fragmentIndex = urlStr.find('#'); + if (fragmentIndex != -1) + urlStr = urlStr.left(fragmentIndex); + String headers; + if (!referrer.isEmpty()) + headers += String("Referer: ") + referrer + "\r\n"; + + urlHandle = InternetOpenUrlA(internetHandle, urlStr.latin1().data(), + headers.latin1().data(), headers.length(), + flags, (DWORD_PTR)d->m_jobId); + } + + if (urlHandle == INVALID_HANDLE_VALUE) { + delete this; + return false; + } + d->m_threadId = GetCurrentThreadId(); + + return true; + } +} + +void ResourceHandle::fileLoadTimer(Timer<ResourceHandle>* timer) +{ + ResourceResponse response; + client()->didReceiveResponse(this, response); + + bool result = false; + DWORD bytesRead = 0; + + do { + const int bufferSize = 8192; + char buffer[bufferSize]; + result = ReadFile(d->m_fileHandle, &buffer, bufferSize, &bytesRead, NULL); + if (result && bytesRead) + client()->didReceiveData(this, buffer, bytesRead, 0); + // Check for end of file. + } while (result && bytesRead); + + // FIXME: handle errors better + + CloseHandle(d->m_fileHandle); + d->m_fileHandle = INVALID_HANDLE_VALUE; + + client()->didFinishLoading(this); +} + +void ResourceHandle::cancel() +{ + if (d->m_resourceHandle) + InternetCloseHandle(d->m_resourceHandle); + else + d->m_fileLoadTimer.stop(); + + client()->didFinishLoading(this); + + if (!d->m_resourceHandle) + // Async load canceled before we have a handle -- mark ourselves as in error, to be deleted later. + // FIXME: need real cancel error + client()->didFail(this, ResourceError()); +} + +void ResourceHandle::setHasReceivedResponse(bool b) +{ + d->m_hasReceivedResponse = b; +} + +bool ResourceHandle::hasReceivedResponse() const +{ + return d->m_hasReceivedResponse; +} + +} // namespace WebCore diff --git a/WebCore/platform/network/win/ResourceHandleWin.h b/WebCore/platform/network/win/ResourceHandleWin.h new file mode 100644 index 0000000..2964bcb --- /dev/null +++ b/WebCore/platform/network/win/ResourceHandleWin.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2004, 2006 Apple Computer, 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 ResourceHandleWin_h +#define ResourceHandleWin_h + +#include <windows.h> + +namespace WebCore { + +struct PlatformDataStruct +{ + DWORD error; + BOOL loaded; + LPTSTR errorString; +}; + +struct PlatformResponseStruct +{ +}; + +} + +#endif |