source: webkit/trunk/WebCore/platform/network/cf/ResourceResponseCFNet.cpp @ 29841

Last change on this file since 29841 was 29841, checked in by Adam Roben, 16 years ago

Fix <rdar://5555260> Gmail doesn't load when a user stylesheet is specified

Reviewed by Darin.

A null value exception was being thrown in Gmail's JS code because a
call to document.write failed. document.write failed because
Document::close had not yet been called. Document::close was not
called because the Document was considered to not be "complete" in
FrameLoader::checkComplete because the user stylesheet was in the
process of loading. The user stylesheet was loading because it had
previously been evicted from the cache and was loading fresh from
disk. It had been evicted from the cache because the calculation of
the expiration date was incorrectly casting/overflowing in
ResourceResponseCFNet.cpp.

We now calculate the expiration date in a way that does not cause us
to overflow a time_t, and we correctly clamp the value to the range of
a time_t. I also made the fix for the last modified date, though that
was not causing any bug I am aware of.

In the long-term it seems like whether or not Document::close is
called should not be dependent upon whether the user stylesheet has
finished loading or not.

  • platform/network/cf/ResourceResponseCFNet.cpp: (WebCore::toTimeT): Added. Converts from CFAbsoluteTime to time_t and clamps to the range of time_t. (WebCore::ResourceResponse::doUpdateResourceResponse): Call toTimeT.
  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1/*
2 * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "ResourceResponseCFNet.h"
28
29#include "HTTPParsers.h"
30#include "MIMETypeRegistry.h"
31#include "ResourceResponse.h"
32#include <CFNetwork/CFURLResponsePriv.h>
33#include <wtf/RetainPtr.h>
34
35using namespace std;
36
37// We would like a better value for a maximum time_t,
38// but there is no way to do that in C with any certainty.
39// INT_MAX should work well enough for our purposes.
40#define MAX_TIME_T ((time_t)INT_MAX)   
41
42namespace WebCore {
43
44CFURLResponseRef ResourceResponse::cfURLResponse() const
45
46    return m_cfResponse.get();
47}
48
49static inline bool filenameHasSaneExtension(const String& filename)
50{
51    int dot = filename.find('.');
52
53    // The dot can't be the first or last character in the filename.
54    int length = filename.length();
55    return dot > 0 && dot < length - 1;
56}
57
58static time_t toTimeT(CFAbsoluteTime time)
59{
60    static const double maxTimeAsDouble = std::numeric_limits<time_t>::max();
61    static const double minTimeAsDouble = std::numeric_limits<time_t>::min();
62    return min(max(minTimeAsDouble, time + kCFAbsoluteTimeIntervalSince1970), maxTimeAsDouble);
63}
64
65void ResourceResponse::doUpdateResourceResponse()
66{
67    if (!m_cfResponse.get())
68        return;
69
70    // FIXME: We may need to do MIME type sniffing here (unless that is done in CFURLResponseGetMIMEType).
71
72    m_url = CFURLResponseGetURL(m_cfResponse.get());
73    m_mimeType = CFURLResponseGetMIMEType(m_cfResponse.get());
74    m_expectedContentLength = CFURLResponseGetExpectedContentLength(m_cfResponse.get());
75    m_textEncodingName = CFURLResponseGetTextEncodingName(m_cfResponse.get());
76
77    m_expirationDate = toTimeT(CFURLResponseGetExpirationTime(m_cfResponse.get()));
78    m_lastModifiedDate = toTimeT(CFURLResponseGetLastModifiedDate(m_cfResponse.get()));
79
80    RetainPtr<CFStringRef> suggestedFilename(AdoptCF, CFURLResponseCopySuggestedFilename(m_cfResponse.get()));
81    m_suggestedFilename = suggestedFilename.get();
82
83    CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(m_cfResponse.get());
84    if (httpResponse) {
85        m_httpStatusCode = CFHTTPMessageGetResponseStatusCode(httpResponse);
86
87        RetainPtr<CFStringRef> statusLine(AdoptCF, CFHTTPMessageCopyResponseStatusLine(httpResponse));
88        String statusText(statusLine.get());
89        int spacePos = statusText.find(" ");
90        if (spacePos != -1)
91            statusText = statusText.substring(spacePos + 1);
92        m_httpStatusText = statusText;
93
94        RetainPtr<CFDictionaryRef> headers(AdoptCF, CFHTTPMessageCopyAllHeaderFields(httpResponse));
95        CFIndex headerCount = CFDictionaryGetCount(headers.get());
96        Vector<const void*, 128> keys(headerCount);
97        Vector<const void*, 128> values(headerCount);
98        CFDictionaryGetKeysAndValues(headers.get(), keys.data(), values.data());
99        for (int i = 0; i < headerCount; ++i)
100            m_httpHeaderFields.set((CFStringRef)keys[i], (CFStringRef)values[i]);
101    } else
102        m_httpStatusCode = 0;
103
104    // FIXME: This is a workaround for <rdar://problem/5695848>. This code should be removed once that bug is fixed.
105    if (m_url.isLocalFile() && ( m_mimeType == "text/html" || m_mimeType == "text/plain" )) {
106        const String& path = m_url.path();
107        static const String xhtmlExt(".xhtml");
108        static const String htmlExt(".html");
109        static const String xmlExt(".xml");
110        static const String svgExt(".svg");
111        static const String jsExt(".js");
112        if (path.endsWith(xhtmlExt, false))
113            m_mimeType = "application/xhtml+xml";
114        else if (path.endsWith(htmlExt, false))
115            m_mimeType = "text/html";
116        else if (path.endsWith(xmlExt, false))
117            m_mimeType = "text/xml";
118        else if (path.endsWith(jsExt, false))
119            m_mimeType = "text/javascript";
120        else if (path.endsWith(svgExt, false))
121            m_mimeType = "image/svg+xml";
122    }
123}
124
125}
Note: See TracBrowser for help on using the repository browser.