ResourceHandle.cpp revision cad810f21b803229eb11403f9209855525a25d57
1/*
2 * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 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 "ResourceHandle.h"
28#include "ResourceHandleInternal.h"
29
30#include "BlobRegistry.h"
31#include "DNS.h"
32#include "Logging.h"
33#include "ResourceHandleClient.h"
34#include "Timer.h"
35#include <algorithm>
36
37namespace WebCore {
38
39static bool shouldForceContentSniffing;
40
41ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, bool shouldContentSniff)
42    : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff && shouldContentSniffURL(request.url())))
43{
44    if (!request.url().isValid()) {
45        scheduleFailure(InvalidURLFailure);
46        return;
47    }
48
49    if (!portAllowed(request.url())) {
50        scheduleFailure(BlockedFailure);
51        return;
52    }
53}
54
55PassRefPtr<ResourceHandle> ResourceHandle::create(NetworkingContext* context, const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, bool shouldContentSniff)
56{
57#if ENABLE(BLOB)
58    if (request.url().protocolIs("blob")) {
59        PassRefPtr<ResourceHandle> handle = blobRegistry().createResourceHandle(request, client);
60        if (handle)
61            return handle;
62    }
63#endif
64
65    RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff)));
66
67    if (newHandle->d->m_scheduledFailureType != NoFailure)
68        return newHandle.release();
69
70    if (newHandle->start(context))
71        return newHandle.release();
72
73    return 0;
74}
75
76void ResourceHandle::scheduleFailure(FailureType type)
77{
78    d->m_scheduledFailureType = type;
79    d->m_failureTimer.startOneShot(0);
80}
81
82void ResourceHandle::fireFailure(Timer<ResourceHandle>*)
83{
84    if (!client())
85        return;
86
87    switch (d->m_scheduledFailureType) {
88        case NoFailure:
89            ASSERT_NOT_REACHED();
90            return;
91        case BlockedFailure:
92            d->m_scheduledFailureType = NoFailure;
93            client()->wasBlocked(this);
94            return;
95        case InvalidURLFailure:
96            d->m_scheduledFailureType = NoFailure;
97            client()->cannotShowURL(this);
98            return;
99    }
100
101    ASSERT_NOT_REACHED();
102}
103
104ResourceHandleClient* ResourceHandle::client() const
105{
106    return d->m_client;
107}
108
109void ResourceHandle::setClient(ResourceHandleClient* client)
110{
111    d->m_client = client;
112}
113
114ResourceRequest& ResourceHandle::firstRequest()
115{
116    return d->m_firstRequest;
117}
118
119const String& ResourceHandle::lastHTTPMethod() const
120{
121    return d->m_lastHTTPMethod;
122}
123
124bool ResourceHandle::hasAuthenticationChallenge() const
125{
126    return !d->m_currentWebChallenge.isNull();
127}
128
129void ResourceHandle::clearAuthentication()
130{
131#if PLATFORM(MAC)
132    d->m_currentMacChallenge = nil;
133#endif
134    d->m_currentWebChallenge.nullify();
135}
136
137bool ResourceHandle::shouldContentSniff() const
138{
139    return d->m_shouldContentSniff;
140}
141
142bool ResourceHandle::shouldContentSniffURL(const KURL& url)
143{
144#if PLATFORM(MAC)
145    if (shouldForceContentSniffing)
146        return true;
147#endif
148    // We shouldn't content sniff file URLs as their MIME type should be established via their extension.
149    return !url.protocolIs("file");
150}
151
152void ResourceHandle::forceContentSniffing()
153{
154    shouldForceContentSniffing = true;
155}
156
157void ResourceHandle::setDefersLoading(bool defers)
158{
159    LOG(Network, "Handle %p setDefersLoading(%s)", this, defers ? "true" : "false");
160
161    ASSERT(d->m_defersLoading != defers); // Deferring is not counted, so calling setDefersLoading() repeatedly is likely to be in error.
162    d->m_defersLoading = defers;
163
164    if (defers) {
165        ASSERT(d->m_failureTimer.isActive() == (d->m_scheduledFailureType != NoFailure));
166        if (d->m_failureTimer.isActive())
167            d->m_failureTimer.stop();
168    } else if (d->m_scheduledFailureType != NoFailure) {
169        ASSERT(!d->m_failureTimer.isActive());
170        d->m_failureTimer.startOneShot(0);
171    }
172
173    platformSetDefersLoading(defers);
174}
175
176#if !USE(SOUP)
177void ResourceHandle::prepareForURL(const KURL& url)
178{
179    return prefetchDNS(url.host());
180}
181#endif
182
183void ResourceHandle::cacheMetadata(const ResourceResponse&, const Vector<char>&)
184{
185    // Optionally implemented by platform.
186}
187
188} // namespace WebCore
189