Home | History | Annotate | Download | only in loader
      1 /*
      2  * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      4  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  *
     10  * 1.  Redistributions of source code must retain the above copyright
     11  *     notice, this list of conditions and the following disclaimer.
     12  * 2.  Redistributions in binary form must reproduce the above copyright
     13  *     notice, this list of conditions and the following disclaimer in the
     14  *     documentation and/or other materials provided with the distribution.
     15  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     16  *     its contributors may be used to endorse or promote products derived
     17  *     from this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     22  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "PolicyChecker.h"
     33 
     34 #include "DocumentLoader.h"
     35 #include "FormState.h"
     36 #include "Frame.h"
     37 #include "FrameLoader.h"
     38 #include "FrameLoaderClient.h"
     39 #include "HTMLFormElement.h"
     40 
     41 namespace WebCore {
     42 
     43 PolicyChecker::PolicyChecker(Frame* frame)
     44     : m_frame(frame)
     45     , m_delegateIsDecidingNavigationPolicy(false)
     46     , m_delegateIsHandlingUnimplementablePolicy(false)
     47     , m_loadType(FrameLoadTypeStandard)
     48 {
     49 }
     50 
     51 void PolicyChecker::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
     52 {
     53     checkNavigationPolicy(newRequest, m_frame->loader()->activeDocumentLoader(), 0, function, argument);
     54 }
     55 
     56 void PolicyChecker::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
     57     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
     58 {
     59     NavigationAction action = loader->triggeringAction();
     60     if (action.isEmpty()) {
     61         action = NavigationAction(request.url(), NavigationTypeOther);
     62         loader->setTriggeringAction(action);
     63     }
     64 
     65     // Don't ask more than once for the same request or if we are loading an empty URL.
     66     // This avoids confusion on the part of the client.
     67     if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
     68         function(argument, request, 0, true);
     69         loader->setLastCheckedRequest(request);
     70         return;
     71     }
     72 
     73     // We are always willing to show alternate content for unreachable URLs;
     74     // treat it like a reload so it maintains the right state for b/f list.
     75     if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
     76         if (isBackForwardLoadType(m_loadType))
     77             m_loadType = FrameLoadTypeReload;
     78         function(argument, request, 0, true);
     79         return;
     80     }
     81 
     82     loader->setLastCheckedRequest(request);
     83 
     84     m_callback.set(request, formState.get(), function, argument);
     85 
     86     m_delegateIsDecidingNavigationPolicy = true;
     87     m_frame->loader()->client()->dispatchDecidePolicyForNavigationAction(&PolicyChecker::continueAfterNavigationPolicy,
     88         action, request, formState);
     89     m_delegateIsDecidingNavigationPolicy = false;
     90 }
     91 
     92 void PolicyChecker::checkNewWindowPolicy(const NavigationAction& action, NewWindowPolicyDecisionFunction function,
     93     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, void* argument)
     94 {
     95     m_callback.set(request, formState, frameName, action, function, argument);
     96     m_frame->loader()->client()->dispatchDecidePolicyForNewWindowAction(&PolicyChecker::continueAfterNewWindowPolicy,
     97         action, request, formState, frameName);
     98 }
     99 
    100 void PolicyChecker::checkContentPolicy(const ResourceResponse& response, ContentPolicyDecisionFunction function, void* argument)
    101 {
    102     m_callback.set(function, argument);
    103     m_frame->loader()->client()->dispatchDecidePolicyForResponse(&PolicyChecker::continueAfterContentPolicy,
    104         response, m_frame->loader()->activeDocumentLoader()->request());
    105 }
    106 
    107 void PolicyChecker::cancelCheck()
    108 {
    109     m_frame->loader()->client()->cancelPolicyCheck();
    110     m_callback.clear();
    111 }
    112 
    113 void PolicyChecker::stopCheck()
    114 {
    115     m_frame->loader()->client()->cancelPolicyCheck();
    116     PolicyCallback callback = m_callback;
    117     m_callback.clear();
    118     callback.cancel();
    119 }
    120 
    121 void PolicyChecker::cannotShowMIMEType(const ResourceResponse& response)
    122 {
    123     handleUnimplementablePolicy(m_frame->loader()->client()->cannotShowMIMETypeError(response));
    124 }
    125 
    126 void PolicyChecker::continueLoadAfterWillSubmitForm(PolicyAction)
    127 {
    128     // See header file for an explaination of why this function
    129     // isn't like the others.
    130     m_frame->loader()->continueLoadAfterWillSubmitForm();
    131 }
    132 
    133 void PolicyChecker::continueAfterNavigationPolicy(PolicyAction policy)
    134 {
    135     PolicyCallback callback = m_callback;
    136     m_callback.clear();
    137 
    138     bool shouldContinue = policy == PolicyUse;
    139 
    140     switch (policy) {
    141         case PolicyIgnore:
    142             callback.clearRequest();
    143             break;
    144         case PolicyDownload:
    145             m_frame->loader()->client()->startDownload(callback.request());
    146             callback.clearRequest();
    147             break;
    148         case PolicyUse: {
    149             ResourceRequest request(callback.request());
    150 
    151             if (!m_frame->loader()->client()->canHandleRequest(request)) {
    152                 handleUnimplementablePolicy(m_frame->loader()->cannotShowURLError(callback.request()));
    153                 callback.clearRequest();
    154                 shouldContinue = false;
    155             }
    156             break;
    157         }
    158     }
    159 
    160     callback.call(shouldContinue);
    161 }
    162 
    163 void PolicyChecker::continueAfterNewWindowPolicy(PolicyAction policy)
    164 {
    165     PolicyCallback callback = m_callback;
    166     m_callback.clear();
    167 
    168     switch (policy) {
    169         case PolicyIgnore:
    170             callback.clearRequest();
    171             break;
    172         case PolicyDownload:
    173             m_frame->loader()->client()->startDownload(callback.request());
    174             callback.clearRequest();
    175             break;
    176         case PolicyUse:
    177             break;
    178     }
    179 
    180     callback.call(policy == PolicyUse);
    181 }
    182 
    183 void PolicyChecker::continueAfterContentPolicy(PolicyAction policy)
    184 {
    185     PolicyCallback callback = m_callback;
    186     m_callback.clear();
    187     callback.call(policy);
    188 }
    189 
    190 void PolicyChecker::handleUnimplementablePolicy(const ResourceError& error)
    191 {
    192     m_delegateIsHandlingUnimplementablePolicy = true;
    193     m_frame->loader()->client()->dispatchUnableToImplementPolicy(error);
    194     m_delegateIsHandlingUnimplementablePolicy = false;
    195 }
    196 
    197 } // namespace WebCore
    198