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