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
PolicyChecker(Frame * frame)43 PolicyChecker::PolicyChecker(Frame* frame)
44 : m_frame(frame)
45 , m_delegateIsDecidingNavigationPolicy(false)
46 , m_delegateIsHandlingUnimplementablePolicy(false)
47 , m_loadType(FrameLoadTypeStandard)
48 {
49 }
50
checkNavigationPolicy(const ResourceRequest & newRequest,NavigationPolicyDecisionFunction function,void * argument)51 void PolicyChecker::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
52 {
53 checkNavigationPolicy(newRequest, m_frame->loader()->activeDocumentLoader(), 0, function, argument);
54 }
55
checkNavigationPolicy(const ResourceRequest & request,DocumentLoader * loader,PassRefPtr<FormState> formState,NavigationPolicyDecisionFunction function,void * argument)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
checkNewWindowPolicy(const NavigationAction & action,NewWindowPolicyDecisionFunction function,const ResourceRequest & request,PassRefPtr<FormState> formState,const String & frameName,void * argument)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
checkContentPolicy(const ResourceResponse & response,ContentPolicyDecisionFunction function,void * argument)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
cancelCheck()107 void PolicyChecker::cancelCheck()
108 {
109 m_frame->loader()->client()->cancelPolicyCheck();
110 m_callback.clear();
111 }
112
stopCheck()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
cannotShowMIMEType(const ResourceResponse & response)121 void PolicyChecker::cannotShowMIMEType(const ResourceResponse& response)
122 {
123 handleUnimplementablePolicy(m_frame->loader()->client()->cannotShowMIMETypeError(response));
124 }
125
continueLoadAfterWillSubmitForm(PolicyAction)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
continueAfterNavigationPolicy(PolicyAction policy)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
continueAfterNewWindowPolicy(PolicyAction policy)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
continueAfterContentPolicy(PolicyAction policy)183 void PolicyChecker::continueAfterContentPolicy(PolicyAction policy)
184 {
185 PolicyCallback callback = m_callback;
186 m_callback.clear();
187 callback.call(policy);
188 }
189
handleUnimplementablePolicy(const ResourceError & error)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