Home | History | Annotate | Download | only in network
      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 #include <wtf/text/CString.h>
     37 
     38 namespace WebCore {
     39 
     40 static bool shouldForceContentSniffing;
     41 
     42 ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, bool shouldContentSniff)
     43     : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff && shouldContentSniffURL(request.url())))
     44 {
     45     if (!request.url().isValid()) {
     46         scheduleFailure(InvalidURLFailure);
     47         return;
     48     }
     49 
     50     if (!portAllowed(request.url())) {
     51         scheduleFailure(BlockedFailure);
     52         return;
     53     }
     54 }
     55 
     56 PassRefPtr<ResourceHandle> ResourceHandle::create(NetworkingContext* context, const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, bool shouldContentSniff)
     57 {
     58 #if ENABLE(BLOB)
     59     if (request.url().protocolIs("blob")) {
     60         PassRefPtr<ResourceHandle> handle = blobRegistry().createResourceHandle(request, client);
     61         if (handle)
     62             return handle;
     63     }
     64 #endif
     65 
     66     RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff)));
     67 
     68     if (newHandle->d->m_scheduledFailureType != NoFailure)
     69         return newHandle.release();
     70 
     71     if (newHandle->start(context))
     72         return newHandle.release();
     73 
     74     return 0;
     75 }
     76 
     77 void ResourceHandle::scheduleFailure(FailureType type)
     78 {
     79     d->m_scheduledFailureType = type;
     80     d->m_failureTimer.startOneShot(0);
     81 }
     82 
     83 void ResourceHandle::fireFailure(Timer<ResourceHandle>*)
     84 {
     85     if (!client())
     86         return;
     87 
     88     switch (d->m_scheduledFailureType) {
     89         case NoFailure:
     90             ASSERT_NOT_REACHED();
     91             return;
     92         case BlockedFailure:
     93             d->m_scheduledFailureType = NoFailure;
     94             client()->wasBlocked(this);
     95             return;
     96         case InvalidURLFailure:
     97             d->m_scheduledFailureType = NoFailure;
     98             client()->cannotShowURL(this);
     99             return;
    100     }
    101 
    102     ASSERT_NOT_REACHED();
    103 }
    104 
    105 ResourceHandleClient* ResourceHandle::client() const
    106 {
    107     return d->m_client;
    108 }
    109 
    110 void ResourceHandle::setClient(ResourceHandleClient* client)
    111 {
    112     d->m_client = client;
    113 }
    114 
    115 ResourceRequest& ResourceHandle::firstRequest()
    116 {
    117     return d->m_firstRequest;
    118 }
    119 
    120 const String& ResourceHandle::lastHTTPMethod() const
    121 {
    122     return d->m_lastHTTPMethod;
    123 }
    124 
    125 bool ResourceHandle::hasAuthenticationChallenge() const
    126 {
    127     return !d->m_currentWebChallenge.isNull();
    128 }
    129 
    130 void ResourceHandle::clearAuthentication()
    131 {
    132 #if PLATFORM(MAC)
    133     d->m_currentMacChallenge = nil;
    134 #endif
    135     d->m_currentWebChallenge.nullify();
    136 }
    137 
    138 bool ResourceHandle::shouldContentSniff() const
    139 {
    140     return d->m_shouldContentSniff;
    141 }
    142 
    143 bool ResourceHandle::shouldContentSniffURL(const KURL& url)
    144 {
    145 #if PLATFORM(MAC)
    146     if (shouldForceContentSniffing)
    147         return true;
    148 #endif
    149     // We shouldn't content sniff file URLs as their MIME type should be established via their extension.
    150     return !url.protocolIs("file");
    151 }
    152 
    153 void ResourceHandle::forceContentSniffing()
    154 {
    155     shouldForceContentSniffing = true;
    156 }
    157 
    158 void ResourceHandle::setDefersLoading(bool defers)
    159 {
    160     LOG(Network, "Handle %p setDefersLoading(%s)", this, defers ? "true" : "false");
    161 
    162     ASSERT(d->m_defersLoading != defers); // Deferring is not counted, so calling setDefersLoading() repeatedly is likely to be in error.
    163     d->m_defersLoading = defers;
    164 
    165     if (defers) {
    166         ASSERT(d->m_failureTimer.isActive() == (d->m_scheduledFailureType != NoFailure));
    167         if (d->m_failureTimer.isActive())
    168             d->m_failureTimer.stop();
    169     } else if (d->m_scheduledFailureType != NoFailure) {
    170         ASSERT(!d->m_failureTimer.isActive());
    171         d->m_failureTimer.startOneShot(0);
    172     }
    173 
    174     platformSetDefersLoading(defers);
    175 }
    176 
    177 #if !USE(SOUP)
    178 void ResourceHandle::prepareForURL(const KURL& url)
    179 {
    180     return prefetchDNS(url.host());
    181 }
    182 #endif
    183 
    184 void ResourceHandle::cacheMetadata(const ResourceResponse&, const Vector<char>&)
    185 {
    186     // Optionally implemented by platform.
    187 }
    188 
    189 #if USE(CFURLSTORAGESESSIONS)
    190 
    191 static RetainPtr<CFURLStorageSessionRef>& privateStorageSession()
    192 {
    193     DEFINE_STATIC_LOCAL(RetainPtr<CFURLStorageSessionRef>, storageSession, ());
    194     return storageSession;
    195 }
    196 
    197 static String& privateBrowsingStorageSessionIdentifierBase()
    198 {
    199     DEFINE_STATIC_LOCAL(String, base, ());
    200     return base;
    201 }
    202 
    203 void ResourceHandle::setPrivateBrowsingEnabled(bool enabled)
    204 {
    205     if (!enabled) {
    206         privateStorageSession() = nullptr;
    207         return;
    208     }
    209 
    210     if (privateStorageSession())
    211         return;
    212 
    213     String base = privateBrowsingStorageSessionIdentifierBase().isNull() ? privateBrowsingStorageSessionIdentifierDefaultBase() : privateBrowsingStorageSessionIdentifierBase();
    214     RetainPtr<CFStringRef> cfIdentifier(AdoptCF, String::format("%s.PrivateBrowsing", base.utf8().data()).createCFString());
    215 
    216     privateStorageSession() = createPrivateBrowsingStorageSession(cfIdentifier.get());
    217 }
    218 
    219 CFURLStorageSessionRef ResourceHandle::privateBrowsingStorageSession()
    220 {
    221     return privateStorageSession().get();
    222 }
    223 
    224 void ResourceHandle::setPrivateBrowsingStorageSessionIdentifierBase(const String& identifier)
    225 {
    226     privateBrowsingStorageSessionIdentifierBase() = identifier;
    227 }
    228 
    229 #endif // USE(CFURLSTORAGESESSIONS)
    230 
    231 } // namespace WebCore
    232