blob: be6ca76939900bcce63d83052b81405efd604a94 [file] [log] [blame]
darinfa7a4e32006-10-30 00:37:02 +00001/*
bfulgham@apple.com2187dd52020-06-10 23:11:41 +00002 * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
hausmann@webkit.orgf6964472008-09-29 12:47:08 +00003 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
staikos@webkit.org159f11f2009-05-18 23:48:30 +00004 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
staikos@webkit.orgc7692122009-10-28 18:12:34 +00005 * Copyright (C) 2008 Alp Toker <alp@atoker.com>
6 * Copyright (C) Research In Motion Limited 2009. All rights reserved.
commit-queue@webkit.orgff400aa2011-03-10 23:43:48 +00007 * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
commit-queue@webkit.org343b8a62011-09-21 01:49:03 +00008 * Copyright (C) 2011 Google Inc. All rights reserved.
darinfa7a4e32006-10-30 00:37:02 +00009 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
joepeck@webkit.org6d6a47c2014-03-06 19:33:51 +000015 * notice, this list of conditions and the following disclaimer.
darinfa7a4e32006-10-30 00:37:02 +000016 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
joepeck@webkit.org6d6a47c2014-03-06 19:33:51 +000018 * documentation and/or other materials provided with the distribution.
mjs@apple.com92047332014-03-15 04:08:27 +000019 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
darinfa7a4e32006-10-30 00:37:02 +000020 * its contributors may be used to endorse or promote products derived
joepeck@webkit.org6d6a47c2014-03-06 19:33:51 +000021 * from this software without specific prior written permission.
darinfa7a4e32006-10-30 00:37:02 +000022 *
23 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
24 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
27 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
darinc1116552006-10-30 20:05:39 +000035#include "config.h"
36#include "FrameLoader.h"
darinfa7a4e32006-10-30 00:37:02 +000037
mario@webkit.org685258f2011-12-06 00:10:55 +000038#include "AXObjectCache.h"
darin@chromium.orgdf437532009-08-05 00:18:28 +000039#include "ApplicationCacheHost.h"
cdumez@apple.com9265dfe2019-10-17 01:44:16 +000040#include "BackForwardCache.h"
darin@apple.come10e1282010-10-30 00:44:33 +000041#include "BackForwardController.h"
beidson@apple.com7617ce72010-05-13 20:31:46 +000042#include "BeforeUnloadEvent.h"
beidson448a6e72007-04-10 23:55:56 +000043#include "CachedPage.h"
darin@apple.come10e1282010-10-30 00:44:33 +000044#include "CachedResourceLoader.h"
ggaren52fd1072006-11-06 23:56:59 +000045#include "Chrome.h"
commit-queue@webkit.org52b68332011-06-07 16:20:07 +000046#include "ChromeClient.h"
beidson@apple.com7034ec72017-07-06 00:01:53 +000047#include "CommonVM.h"
aestes@apple.com176a9aa2016-07-08 20:14:34 +000048#include "ContentFilter.h"
achristensen@apple.comd3edc2a2019-03-21 20:23:46 +000049#include "ContentRuleListResults.h"
abarth@webkit.orgf921dee2011-03-26 11:59:34 +000050#include "ContentSecurityPolicy.h"
aroben@apple.com92cfa902008-04-16 19:19:00 +000051#include "DOMWindow.h"
mark.lam@apple.com45beb072012-12-12 23:04:20 +000052#include "DatabaseManager.h"
jer.noble@apple.com9e0f0602014-11-22 05:27:16 +000053#include "DiagnosticLoggingClient.h"
eric.carlson@apple.com77b4a112014-10-30 19:04:29 +000054#include "DiagnosticLoggingKeys.h"
darinc370e7e2006-11-08 05:52:27 +000055#include "Document.h"
darinc1116552006-10-30 20:05:39 +000056#include "DocumentLoader.h"
darinc370e7e2006-11-08 05:52:27 +000057#include "Editor.h"
anderscaf6232012006-11-15 00:36:50 +000058#include "EditorClient.h"
ggaren52fd1072006-11-06 23:56:59 +000059#include "Element.h"
darinf1bb0042006-12-01 22:46:21 +000060#include "Event.h"
weinig@apple.com13d777f2013-04-16 21:54:22 +000061#include "EventHandler.h"
darinc370e7e2006-11-08 05:52:27 +000062#include "EventNames.h"
ggaren52fd1072006-11-06 23:56:59 +000063#include "FloatRect.h"
darinc1116552006-10-30 20:05:39 +000064#include "FormState.h"
dglazkov@chromium.org25a57e52010-06-20 21:00:35 +000065#include "FormSubmission.h"
cdumez@apple.comc518f7e2018-04-03 18:01:41 +000066#include "Frame.h"
ggaren52fd1072006-11-06 23:56:59 +000067#include "FrameLoadRequest.h"
68#include "FrameLoaderClient.h"
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +000069#include "FrameNetworkingContext.h"
ggaren52fd1072006-11-06 23:56:59 +000070#include "FrameTree.h"
darinc370e7e2006-11-08 05:52:27 +000071#include "FrameView.h"
akling@apple.comaf7f33b2016-02-06 17:00:30 +000072#include "GCController.h"
darinc370e7e2006-11-08 05:52:27 +000073#include "HTMLFormElement.h"
commit-queue@webkit.orge5739ca2012-11-15 19:39:50 +000074#include "HTMLInputElement.h"
darinc370e7e2006-11-08 05:52:27 +000075#include "HTMLNames.h"
76#include "HTMLObjectElement.h"
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +000077#include "HTMLParserIdioms.h"
andersca@apple.coma96cf712014-06-14 17:49:44 +000078#include "HTTPHeaderNames.h"
commit-queue@webkit.orgf1fbce62020-01-01 11:25:53 +000079#include "HTTPHeaderValues.h"
ape9991d52006-12-08 18:19:51 +000080#include "HTTPParsers.h"
andersca@apple.com9b9d83b2013-04-10 19:11:20 +000081#include "HistoryController.h"
weinig62f94be2007-07-18 20:37:20 +000082#include "HistoryItem.h"
cdumez@apple.com8b478c62016-01-23 01:04:59 +000083#include "IgnoreOpensDuringUnloadCountIncrementer.h"
commit-queue@webkit.org4c49a662011-01-02 22:27:10 +000084#include "InspectorController.h"
yurys@chromium.org389a6242011-01-12 13:06:42 +000085#include "InspectorInstrumentation.h"
yoav@yoav.ws1c12d5c2017-01-19 07:13:54 +000086#include "LinkLoader.h"
commit-queue@webkit.org3eeac492016-08-12 22:53:27 +000087#include "LoadTiming.h"
beidson@apple.com0c140b42013-01-17 00:45:30 +000088#include "LoaderStrategy.h"
beidson50c3bd82007-01-03 03:11:18 +000089#include "Logging.h"
weinig@apple.com13d777f2013-04-16 21:54:22 +000090#include "MemoryCache.h"
carlosgc@webkit.org32a60dd2016-11-10 14:24:26 +000091#include "MemoryRelease.h"
rniwa@webkit.orgf694bd62017-06-30 19:32:41 +000092#include "NavigationDisabler.h"
rniwa@webkit.org2c6d4eb2017-07-01 21:26:31 +000093#include "NavigationScheduler.h"
drousso@apple.com21748ed2018-10-08 18:25:52 +000094#include "Node.h"
achristensen@apple.come5945672016-06-13 21:58:53 +000095#include "Page.h"
ggaren@apple.com521f64b2009-09-24 05:53:23 +000096#include "PageTransitionEvent.h"
akling@apple.come6549f42016-12-01 16:15:27 +000097#include "PerformanceLogging.h"
beidson@apple.com0c140b42013-01-17 00:45:30 +000098#include "PlatformStrategies.h"
hausmann@webkit.org9999bb82008-03-10 11:52:27 +000099#include "PluginData.h"
andersca@apple.com641fef92009-01-06 22:57:25 +0000100#include "PluginDocument.h"
abarth@webkit.org401a3792013-03-03 10:12:59 +0000101#include "PolicyChecker.h"
andersca2b2c5ce2007-01-15 21:55:00 +0000102#include "ProgressTracker.h"
beidson50c3bd82007-01-03 03:11:18 +0000103#include "ResourceHandle.h"
beidson@apple.come3ea01d2015-07-02 18:33:23 +0000104#include "ResourceLoadInfo.h"
wilander@apple.com63f925f2016-10-06 17:40:12 +0000105#include "ResourceLoadObserver.h"
darinc370e7e2006-11-08 05:52:27 +0000106#include "ResourceRequest.h"
ossy@webkit.org66d8c0a2014-02-05 11:42:35 +0000107#include "SVGLocatable.h"
108#include "SVGNames.h"
ossy@webkit.org66d8c0a2014-02-05 11:42:35 +0000109#include "SVGViewElement.h"
110#include "SVGViewSpec.h"
weinig@apple.com79099002008-11-21 05:51:28 +0000111#include "ScriptController.h"
darin@chromium.org6b412472008-11-24 23:07:38 +0000112#include "ScriptSourceCode.h"
vsevik@chromium.org53bb0692012-01-18 20:59:10 +0000113#include "ScrollAnimator.h"
weinige06430a2007-10-19 20:53:22 +0000114#include "SecurityOrigin.h"
abarth@webkit.orgeea90662011-11-09 07:58:49 +0000115#include "SecurityPolicy.h"
darinc370e7e2006-11-08 05:52:27 +0000116#include "SegmentedString.h"
yurys@chromium.org832b9142010-08-05 12:36:31 +0000117#include "SerializedScriptValue.h"
darinc370e7e2006-11-08 05:52:27 +0000118#include "Settings.h"
cdumez@apple.comfdb89712018-06-11 20:52:31 +0000119#include "ShouldTreatAsContinuingLoad.h"
rniwa@webkit.org77c65702019-08-13 05:18:11 +0000120#include "StyleTreeResolver.h"
akling@apple.com7f81b1e2013-09-06 17:23:03 +0000121#include "SubframeLoader.h"
dbates@webkit.org3c1f25a2018-02-07 18:56:02 +0000122#include "SubresourceLoader.h"
darin@apple.com1b75e772010-06-15 22:20:34 +0000123#include "TextResourceDecoder.h"
beidson@apple.come3ea01d2015-07-02 18:33:23 +0000124#include "UserContentController.h"
commit-queue@webkit.org635dbdc2017-11-23 19:36:08 +0000125#include "UserGestureIndicator.h"
darin@apple.com1b75e772010-06-15 22:20:34 +0000126#include "WindowFeatures.h"
127#include "XMLDocumentParser.h"
commit-queue@webkit.org1d992932018-09-11 17:14:07 +0000128#include <dom/ScriptDisallowedScope.h>
achristensen@apple.comce5520e2017-09-25 22:33:19 +0000129#include <wtf/CompletionHandler.h>
keith_miller@apple.combb2f61c2018-12-01 03:28:36 +0000130#include <wtf/URL.h>
akling@apple.comf8515982013-09-02 18:50:01 +0000131#include <wtf/Ref.h>
beidson@apple.com1c9022b2018-03-21 00:05:58 +0000132#include <wtf/SetForScope.h>
darin@apple.com1b75e772010-06-15 22:20:34 +0000133#include <wtf/StdLibExtras.h>
simon.fraser@apple.com83325b92017-03-17 00:47:16 +0000134#include <wtf/SystemTracing.h>
darin@apple.com1b75e772010-06-15 22:20:34 +0000135#include <wtf/text/CString.h>
zimmermann@webkit.orgb5e11e62011-05-16 07:56:06 +0000136#include <wtf/text/WTFString.h>
darin@apple.com1b75e772010-06-15 22:20:34 +0000137
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +0000138#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
jeremy@chromium.orgc4b86e32011-02-13 20:28:39 +0000139#include "Archive.h"
jeremy@chromium.orgc4b86e32011-02-13 20:28:39 +0000140#endif
141
enrica@apple.com53b08e52016-01-19 22:58:59 +0000142#if ENABLE(DATA_DETECTION)
143#include "DataDetection.h"
144#endif
145
ap@apple.com1e8475922018-10-18 21:38:50 +0000146#if PLATFORM(IOS_FAMILY)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000147#include "DocumentType.h"
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000148#include "ResourceLoader.h"
cdumez@apple.com0b0e88f2016-03-06 03:28:54 +0000149#include "RuntimeApplicationChecks.h"
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000150#endif
loislo@chromium.org82b9dde2012-09-12 13:16:31 +0000151
krollin@apple.comf26b56e2020-02-28 19:43:33 +0000152#define PAGE_ID ((pageID().valueOr(PageIdentifier())).toUInt64())
153#define FRAME_ID ((frameID().valueOr(FrameIdentifier())).toUInt64())
154#define FRAMELOADER_RELEASE_LOG_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - [pageID=%" PRIu64 ", frameID=%" PRIu64 ", main=%d] FrameLoader::" fmt, this, PAGE_ID, FRAME_ID, m_frame.isMainFrame(), ##__VA_ARGS__)
155#define FRAMELOADER_RELEASE_LOG_ERROR_IF_ALLOWED(channel, fmt, ...) RELEASE_LOG_IF(isAlwaysOnLoggingAllowed(), channel, "%p - [pageID=%" PRIu64 ", frameID=%" PRIu64 ", main=%d] FrameLoader::" fmt, this, PAGE_ID, FRAME_ID, m_frame.isMainFrame(), ##__VA_ARGS__)
commit-queue@webkit.org6d635222016-03-08 06:44:59 +0000156
darinfa7a4e32006-10-30 00:37:02 +0000157namespace WebCore {
158
darin@apple.com1b75e772010-06-15 22:20:34 +0000159using namespace HTMLNames;
oliverb64e4082007-10-12 13:13:51 +0000160using namespace SVGNames;
darinc370e7e2006-11-08 05:52:27 +0000161
darinc370e7e2006-11-08 05:52:27 +0000162bool isBackForwardLoadType(FrameLoadType type)
163{
164 switch (type) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +0000165 case FrameLoadType::Standard:
166 case FrameLoadType::Reload:
167 case FrameLoadType::ReloadFromOrigin:
antti@apple.com5d0c5402017-03-17 19:52:49 +0000168 case FrameLoadType::ReloadExpiredOnly:
andersca@apple.comb50fcc32014-06-19 00:13:20 +0000169 case FrameLoadType::Same:
170 case FrameLoadType::RedirectWithLockedBackForwardList:
171 case FrameLoadType::Replace:
172 return false;
173 case FrameLoadType::Back:
174 case FrameLoadType::Forward:
175 case FrameLoadType::IndexedBackForward:
176 return true;
darinc370e7e2006-11-08 05:52:27 +0000177 }
178 ASSERT_NOT_REACHED();
179 return false;
180}
181
antti@apple.com5d0c5402017-03-17 19:52:49 +0000182bool isReload(FrameLoadType type)
183{
184 switch (type) {
185 case FrameLoadType::Reload:
186 case FrameLoadType::ReloadFromOrigin:
187 case FrameLoadType::ReloadExpiredOnly:
188 return true;
189 case FrameLoadType::Standard:
190 case FrameLoadType::Same:
191 case FrameLoadType::RedirectWithLockedBackForwardList:
192 case FrameLoadType::Replace:
193 case FrameLoadType::Back:
194 case FrameLoadType::Forward:
195 case FrameLoadType::IndexedBackForward:
196 return false;
197 }
198 ASSERT_NOT_REACHED();
199 return false;
200}
201
cjerdonek@webkit.org75d10692010-05-18 16:18:31 +0000202// This is not in the FrameLoader class to emphasize that it does not depend on
203// private FrameLoader data, and to avoid increasing the number of public functions
204// with access to private data. Since only this .cpp file needs it, making it
205// non-member lets us exclude it from the header file, thus keeping FrameLoader.h's
206// API simpler.
207//
cdumez@apple.comd6738dc2015-05-04 23:58:32 +0000208static bool isDocumentSandboxed(Frame& frame, SandboxFlags mask)
cjerdonek@webkit.org75d10692010-05-18 16:18:31 +0000209{
cdumez@apple.comd6738dc2015-05-04 23:58:32 +0000210 return frame.document() && frame.document()->isSandboxed(mask);
cjerdonek@webkit.org75d10692010-05-18 16:18:31 +0000211}
212
cdumez@apple.comfc8fdf32019-12-06 21:05:12 +0000213class PageLevelForbidScope {
214protected:
215 explicit PageLevelForbidScope(Page* page)
216 : m_page(makeWeakPtr(page))
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +0000217 {
cdumez@apple.comfc8fdf32019-12-06 21:05:12 +0000218 }
219
220 ~PageLevelForbidScope() = default;
221
222 WeakPtr<Page> m_page;
223};
224
225struct ForbidPromptsScope : public PageLevelForbidScope {
226 explicit ForbidPromptsScope(Page* page)
227 : PageLevelForbidScope(page)
228 {
229 if (m_page)
230 m_page->forbidPrompts();
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +0000231 }
232
233 ~ForbidPromptsScope()
234 {
cdumez@apple.comfc8fdf32019-12-06 21:05:12 +0000235 if (m_page)
236 m_page->allowPrompts();
237 }
238};
239
240struct ForbidSynchronousLoadsScope : public PageLevelForbidScope {
241 explicit ForbidSynchronousLoadsScope(Page* page)
242 : PageLevelForbidScope(page)
243 {
244 if (m_page)
245 m_page->forbidSynchronousLoads();
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +0000246 }
247
cdumez@apple.comfc8fdf32019-12-06 21:05:12 +0000248 ~ForbidSynchronousLoadsScope()
249 {
250 if (m_page)
251 m_page->allowSynchronousLoads();
252 }
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +0000253};
254
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000255class FrameLoader::FrameProgressTracker {
cdumez@apple.coma738a882016-04-19 18:39:09 +0000256 WTF_MAKE_FAST_ALLOCATED;
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000257public:
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000258 explicit FrameProgressTracker(Frame& frame)
259 : m_frame(frame)
260 , m_inProgress(false)
261 {
262 }
263
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000264 ~FrameProgressTracker()
265 {
jpfau@apple.com7907c6b2014-10-28 22:38:44 +0000266 if (m_inProgress && m_frame.page())
andersca@apple.comcd088792014-01-10 07:19:29 +0000267 m_frame.page()->progress().progressCompleted(m_frame);
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000268 }
269
270 void progressStarted()
271 {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000272 ASSERT(m_frame.page());
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000273 if (!m_inProgress)
andersca@apple.comcd088792014-01-10 07:19:29 +0000274 m_frame.page()->progress().progressStarted(m_frame);
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000275 m_inProgress = true;
276 }
277
278 void progressCompleted()
279 {
280 ASSERT(m_inProgress);
akling@apple.com7f50aae2013-08-22 16:01:31 +0000281 ASSERT(m_frame.page());
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000282 m_inProgress = false;
andersca@apple.comcd088792014-01-10 07:19:29 +0000283 m_frame.page()->progress().progressCompleted(m_frame);
cdumez@apple.comc2b1e2a2019-09-04 03:13:45 +0000284 platformStrategies()->loaderStrategy()->pageLoadCompleted(*m_frame.page());
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000285 }
286
287private:
akling@apple.com7f50aae2013-08-22 16:01:31 +0000288 Frame& m_frame;
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000289 bool m_inProgress;
290};
291
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000292FrameLoader::FrameLoader(Frame& frame, UniqueRef<FrameLoaderClient>&& client)
darinfa7a4e32006-10-30 00:37:02 +0000293 : m_frame(frame)
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000294 , m_client(WTFMove(client))
ysuzuki@apple.com1d8e24d2019-08-19 06:59:40 +0000295 , m_policyChecker(makeUnique<PolicyChecker>(frame))
296 , m_history(makeUnique<HistoryController>(frame))
akling@apple.com654fd9a2013-10-06 21:07:29 +0000297 , m_notifier(frame)
ysuzuki@apple.com1d8e24d2019-08-19 06:59:40 +0000298 , m_subframeLoader(makeUnique<SubframeLoader>(frame))
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000299 , m_mixedContentChecker(frame)
japhet@chromium.orgce6c1ba2012-11-28 19:30:48 +0000300 , m_state(FrameStateProvisional)
andersca@apple.comb50fcc32014-06-19 00:13:20 +0000301 , m_loadType(FrameLoadType::Standard)
darinfa7a4e32006-10-30 00:37:02 +0000302 , m_quickRedirectComing(false)
303 , m_sentRedirectNotification(false)
darinc370e7e2006-11-08 05:52:27 +0000304 , m_inStopAllLoaders(false)
darinc370e7e2006-11-08 05:52:27 +0000305 , m_isExecutingJavaScriptFormAction(false)
japhet@chromium.orgce6c1ba2012-11-28 19:30:48 +0000306 , m_didCallImplicitClose(true)
darinc370e7e2006-11-08 05:52:27 +0000307 , m_wasUnloadEventEmitted(false)
308 , m_isComplete(false)
darinc370e7e2006-11-08 05:52:27 +0000309 , m_needsClear(false)
andersca@apple.com574a7452014-11-21 20:10:13 +0000310 , m_checkTimer(*this, &FrameLoader::checkTimerFired)
darin@apple.comf53381b2009-09-23 23:27:01 +0000311 , m_shouldCallCheckCompleted(false)
312 , m_shouldCallCheckLoadComplete(false)
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000313 , m_opener(nullptr)
beidson@apple.comac095c02009-08-18 01:37:56 +0000314 , m_loadingFromCachedPage(false)
beidson@apple.com1390a812013-07-20 06:43:51 +0000315 , m_currentNavigationHasShownBeforeUnloadConfirmPanel(false)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000316 , m_loadsSynchronously(false)
abarth@webkit.orgf2c54c22010-04-11 06:57:13 +0000317 , m_forcedSandboxFlags(SandboxNone)
darinfa7a4e32006-10-30 00:37:02 +0000318{
319}
320
321FrameLoader::~FrameLoader()
322{
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000323 setOpener(nullptr);
cdumez@apple.comf6bbf482019-10-12 19:17:37 +0000324 detachFromAllOpenedFrames();
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +0000325
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +0000326 if (m_networkingContext)
327 m_networkingContext->invalidate();
darinfa7a4e32006-10-30 00:37:02 +0000328}
329
cdumez@apple.comf6bbf482019-10-12 19:17:37 +0000330void FrameLoader::detachFromAllOpenedFrames()
331{
332 for (auto& frame : m_openedFrames)
achristensen@apple.com2ace43d2020-11-05 16:54:48 +0000333 frame.loader().m_opener = nullptr;
cdumez@apple.comf6bbf482019-10-12 19:17:37 +0000334 m_openedFrames.clear();
335}
336
mrowe@apple.com5d92f2a2008-09-30 21:04:35 +0000337void FrameLoader::init()
mjs8d620d52007-05-10 12:31:42 +0000338{
darin@apple.com73006812011-06-29 20:46:33 +0000339 // This somewhat odd set of steps gives the frame an initial empty document.
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000340 setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(URL({ }, emptyString())), SubstituteData()).ptr());
mjs8d620d52007-05-10 12:31:42 +0000341 setProvisionalDocumentLoader(m_policyDocumentLoader.get());
cdumez@apple.coma0010ff2018-12-13 23:17:44 +0000342 m_provisionalDocumentLoader->startLoadingMainResource();
jpfau@apple.comec9eb512014-07-10 01:13:45 +0000343
344 Ref<Frame> protect(m_frame);
akling@apple.com7f50aae2013-08-22 16:01:31 +0000345 m_frame.document()->cancelParsing();
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000346 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +0000347
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000348 m_networkingContext = m_client->createNetworkingContext();
ysuzuki@apple.com1d8e24d2019-08-19 06:59:40 +0000349 m_progressTracker = makeUnique<FrameProgressTracker>(m_frame);
mjs8d620d52007-05-10 12:31:42 +0000350}
351
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000352void FrameLoader::initForSynthesizedDocument(const URL&)
353{
354 // FIXME: We need to initialize the document URL to the specified URL. Currently the URL is empty and hence
355 // FrameLoader::checkCompleted() will overwrite the URL of the document to be activeDocumentLoader()->documentURL().
356
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000357 auto loader = m_client->createDocumentLoader(ResourceRequest(URL({ }, emptyString())), SubstituteData());
beidson@apple.com10a537f2015-07-09 22:30:42 +0000358 loader->attachToFrame(m_frame);
utatane.tea@gmail.com84077632018-06-23 08:39:34 +0000359 loader->setResponse(ResourceResponse(URL(), "text/html"_s, 0, String()));
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000360 loader->setCommitted(true);
commit-queue@webkit.orgc7c21c92017-10-25 21:17:46 +0000361 setDocumentLoader(loader.ptr());
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000362
363 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
364 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
365 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000366 m_client->transitionToCommittedForNewPage();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000367
368 m_didCallImplicitClose = true;
369 m_isComplete = true;
370 m_state = FrameStateComplete;
371 m_needsClear = true;
372
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000373 m_networkingContext = m_client->createNetworkingContext();
ysuzuki@apple.com1d8e24d2019-08-19 06:59:40 +0000374 m_progressTracker = makeUnique<FrameProgressTracker>(m_frame);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000375}
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000376
krollin@apple.comf26b56e2020-02-28 19:43:33 +0000377Optional<PageIdentifier> FrameLoader::pageID() const
378{
379 return client().pageID();
380}
381
382Optional<FrameIdentifier> FrameLoader::frameID() const
383{
384 return client().frameID();
385}
386
achristensen@apple.com2ace43d2020-11-05 16:54:48 +0000387Frame* FrameLoader::opener()
388{
achristensen@apple.comd1bf54a2020-11-05 17:19:40 +0000389 return m_opener.get();
achristensen@apple.com2ace43d2020-11-05 16:54:48 +0000390}
391
392const Frame* FrameLoader::opener() const
393{
achristensen@apple.comd1bf54a2020-11-05 17:19:40 +0000394 return m_opener.get();
achristensen@apple.com2ace43d2020-11-05 16:54:48 +0000395}
396
darinfa7a4e32006-10-30 00:37:02 +0000397void FrameLoader::setDefersLoading(bool defers)
398{
darin8207db42007-02-20 18:18:39 +0000399 if (m_documentLoader)
400 m_documentLoader->setDefersLoading(defers);
401 if (m_provisionalDocumentLoader)
402 m_provisionalDocumentLoader->setDefersLoading(defers);
403 if (m_policyDocumentLoader)
404 m_policyDocumentLoader->setDefersLoading(defers);
akling@apple.com672cb852013-08-22 20:27:27 +0000405 history().setDefersLoading(defers);
darin@apple.comf53381b2009-09-23 23:27:01 +0000406
407 if (!defers) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000408 m_frame.navigationScheduler().startTimer();
darin@apple.comf53381b2009-09-23 23:27:01 +0000409 startCheckCompleteTimer();
410 }
darinfa7a4e32006-10-30 00:37:02 +0000411}
412
rniwa@webkit.orgba12a012019-02-03 22:48:22 +0000413void FrameLoader::checkContentPolicy(const ResourceResponse& response, PolicyCheckIdentifier identifier, ContentPolicyDecisionFunction&& function)
achristensen@apple.comb8c49be2017-08-23 21:10:09 +0000414{
bfulgham@apple.com78e81d92018-06-25 21:29:50 +0000415 if (!activeDocumentLoader()) {
416 // Load was cancelled
rniwa@webkit.orgba12a012019-02-03 22:48:22 +0000417 function(PolicyAction::Ignore, identifier);
bfulgham@apple.com78e81d92018-06-25 21:29:50 +0000418 return;
419 }
420
rniwa@webkit.orgba12a012019-02-03 22:48:22 +0000421 // FIXME: Validate the policy check identifier.
commit-queue@webkit.orga4a9ce22019-04-10 22:56:35 +0000422 client().dispatchDecidePolicyForResponse(response, activeDocumentLoader()->request(), identifier, activeDocumentLoader()->downloadAttribute(), WTFMove(function));
achristensen@apple.comb8c49be2017-08-23 21:10:09 +0000423}
424
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +0000425void FrameLoader::changeLocation(const URL& url, const String& passedTarget, Event* triggeringEvent, LockHistory lockHistory, LockBackForwardList lockBackForwardList, const ReferrerPolicy& referrerPolicy, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy, Optional<NewFrameOpenerPolicy> openerPolicy, const AtomString& downloadAttribute, const SystemPreviewInfo& systemPreviewInfo, Optional<AdClickAttribution>&& adClickAttribution)
bfulgham@apple.com8f831542016-03-31 15:35:41 +0000426{
beidson@apple.com7034ec72017-07-06 00:01:53 +0000427 auto* frame = lexicalFrameFromCommonVM();
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +0000428 auto initiatedByMainFrame = frame && frame->isMainFrame() ? InitiatedByMainFrame::Yes : InitiatedByMainFrame::Unknown;
beidson@apple.com7034ec72017-07-06 00:01:53 +0000429
commit-queue@webkit.org8383b5f2020-03-02 11:36:00 +0000430 NewFrameOpenerPolicy newFrameOpenerPolicy = openerPolicy.valueOr(referrerPolicy == ReferrerPolicy::NoReferrer ? NewFrameOpenerPolicy::Suppress : NewFrameOpenerPolicy::Allow);
commit-queue@webkit.org1b6bd842020-04-18 17:04:07 +0000431 FrameLoadRequest frameLoadRequest(*m_frame.document(), m_frame.document()->securityOrigin(), { url }, passedTarget, initiatedByMainFrame, downloadAttribute, systemPreviewInfo);
432 frameLoadRequest.setLockHistory(lockHistory);
433 frameLoadRequest.setLockBackForwardList(lockBackForwardList);
434 frameLoadRequest.setNewFrameOpenerPolicy(newFrameOpenerPolicy);
435 frameLoadRequest.setReferrerPolicy(referrerPolicy);
436 frameLoadRequest.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicy);
437 frameLoadRequest.disableShouldReplaceDocumentIfJavaScriptURL();
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +0000438 changeLocation(WTFMove(frameLoadRequest), triggeringEvent, WTFMove(adClickAttribution));
bfulgham@apple.com8f831542016-03-31 15:35:41 +0000439}
440
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +0000441void FrameLoader::changeLocation(FrameLoadRequest&& frameRequest, Event* triggeringEvent, Optional<AdClickAttribution>&& adClickAttribution)
cjerdonek@webkit.org983777f2010-05-17 07:34:12 +0000442{
commit-queue@webkit.org7a3c5522020-03-09 15:10:01 +0000443 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "changeLocation: frame load started");
commit-queue@webkit.org8a13ad32020-03-16 08:11:26 +0000444 ASSERT(frameRequest.resourceRequest().httpMethod() == "GET");
krollin@apple.come1810b62018-12-20 19:23:20 +0000445
akling@apple.comf8515982013-09-02 18:50:01 +0000446 Ref<Frame> protect(m_frame);
darin@apple.com1cf3d562010-12-07 16:23:03 +0000447
commit-queue@webkit.org13f84902020-06-14 06:34:43 +0000448 if (frameRequest.resourceRequest().url().protocolIsJavaScript()) {
449 m_frame.script().executeJavaScriptURL(frameRequest.resourceRequest().url(), &frameRequest.requester().securityOrigin(), frameRequest.shouldReplaceDocumentIfJavaScriptURL());
cdumez@apple.com6cbf70a2019-10-11 20:26:15 +0000450 m_quickRedirectComing = false;
weinig@apple.com6b00e242008-01-08 01:30:27 +0000451 return;
cdumez@apple.com6cbf70a2019-10-11 20:26:15 +0000452 }
weinig@apple.com6b00e242008-01-08 01:30:27 +0000453
darin@apple.com1cf3d562010-12-07 16:23:03 +0000454 if (frameRequest.frameName().isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000455 frameRequest.setFrameName(m_frame.document()->baseTarget());
darinc370e7e2006-11-08 05:52:27 +0000456
bfulgham@apple.comb30d7f82016-06-07 15:47:30 +0000457 m_frame.document()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(frameRequest.resourceRequest(), ContentSecurityPolicy::InsecureRequestType::Navigation);
darin@apple.com4cd1b242009-03-27 23:37:46 +0000458
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +0000459 loadFrameRequest(WTFMove(frameRequest), triggeringEvent, { }, WTFMove(adClickAttribution));
darinc370e7e2006-11-08 05:52:27 +0000460}
461
darin@apple.com961f2a52016-12-31 09:51:29 +0000462void FrameLoader::submitForm(Ref<FormSubmission>&& submission)
darinc370e7e2006-11-08 05:52:27 +0000463{
darin@apple.comc04189e2017-01-18 05:17:17 +0000464 ASSERT(submission->method() == FormSubmission::Method::Post || submission->method() == FormSubmission::Method::Get);
dglazkov@chromium.org25a57e52010-06-20 21:00:35 +0000465
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000466 // FIXME: Find a good spot for these.
darin@apple.comc04189e2017-01-18 05:17:17 +0000467 ASSERT(!submission->state().sourceDocument().frame() || submission->state().sourceDocument().frame() == &m_frame);
dbates@webkit.org29908522017-01-07 07:14:03 +0000468
akling@apple.com7f50aae2013-08-22 16:01:31 +0000469 if (!m_frame.page())
adele@apple.comf3d6b892008-04-29 01:30:20 +0000470 return;
dbates@webkit.org29908522017-01-07 07:14:03 +0000471
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000472 if (submission->action().isEmpty())
darinc370e7e2006-11-08 05:52:27 +0000473 return;
474
cdumez@apple.comd6738dc2015-05-04 23:58:32 +0000475 if (isDocumentSandboxed(m_frame, SandboxForms)) {
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +0000476 // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
joepeck@webkit.org1f45df92014-02-06 23:45:53 +0000477 m_frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked form submission to '" + submission->action().stringCenterEllipsizedToLength() + "' because the form's frame is sandboxed and the 'allow-forms' permission is not set.");
abarth@webkit.orgb8a10552009-12-02 02:40:35 +0000478 return;
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +0000479 }
abarth@webkit.orgb8a10552009-12-02 02:40:35 +0000480
bfulgham@apple.com2187dd52020-06-10 23:11:41 +0000481 URL formAction = submission->action();
482 if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(formAction))
483 return;
484
485 if (formAction.protocolIsJavaScript()) {
darinc370e7e2006-11-08 05:52:27 +0000486 m_isExecutingJavaScriptFormAction = true;
ap@apple.come6afcb62014-04-20 19:02:13 +0000487 Ref<Frame> protect(m_frame);
commit-queue@webkit.org13f84902020-06-14 06:34:43 +0000488 m_frame.script().executeJavaScriptURL(submission->action(), nullptr, DoNotReplaceDocumentIfJavaScriptURL);
darinc370e7e2006-11-08 05:52:27 +0000489 m_isExecutingJavaScriptFormAction = false;
490 return;
491 }
492
darin@apple.comc04189e2017-01-18 05:17:17 +0000493 Frame* targetFrame = findFrameForNavigation(submission->target(), &submission->state().sourceDocument());
darin@apple.com0f88bda2009-04-02 00:30:50 +0000494 if (!targetFrame) {
commit-queue@webkit.org635dbdc2017-11-23 19:36:08 +0000495 if (!DOMWindow::allowPopUp(m_frame) && !UserGestureIndicator::processingUserGesture())
abarth@webkit.orgc72185c2010-04-09 06:43:19 +0000496 return;
497
darin@apple.comc04189e2017-01-18 05:17:17 +0000498 // FIXME: targetFrame can be null for two distinct reasons:
ap@apple.comf8c414e2013-08-13 03:44:57 +0000499 // 1. The frame was not found by name, so we should try opening a new window.
500 // 2. The frame was found, but navigating it was not allowed, e.g. by HTML5 sandbox or by origin checks.
501 // Continuing form submission makes no sense in the latter case.
502 // There is a repeat check after timer fires, so this is not a correctness issue.
503
akling@apple.com7f50aae2013-08-22 16:01:31 +0000504 targetFrame = &m_frame;
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000505 } else
506 submission->clearTarget();
507
darin@apple.com0f88bda2009-04-02 00:30:50 +0000508 if (!targetFrame->page())
darinc370e7e2006-11-08 05:52:27 +0000509 return;
darin@apple.com0f88bda2009-04-02 00:30:50 +0000510
cdumez@apple.comede5bd32019-12-20 00:28:57 +0000511 if (m_frame.tree().isDescendantOf(targetFrame))
commit-queue@webkit.org43964052012-08-13 19:30:15 +0000512 m_submittedFormURL = submission->requestURL();
darinc370e7e2006-11-08 05:52:27 +0000513
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +0000514 submission->setReferrer(outgoingReferrer());
commit-queue@webkit.org138b4142020-03-10 11:27:15 +0000515 submission->setOrigin(SecurityPolicy::generateOriginHeader(m_frame.document()->referrerPolicy(), submission->requestURL(), m_frame.document()->securityOrigin()));
darinc370e7e2006-11-08 05:52:27 +0000516
darin@apple.com961f2a52016-12-31 09:51:29 +0000517 targetFrame->navigationScheduler().scheduleFormSubmission(WTFMove(submission));
darinc370e7e2006-11-08 05:52:27 +0000518}
519
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +0000520void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
darinc370e7e2006-11-08 05:52:27 +0000521{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000522 if (m_frame.document() && m_frame.document()->parser())
523 m_frame.document()->parser()->stopParsing();
mjs8d620d52007-05-10 12:31:42 +0000524
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +0000525 if (unloadEventPolicy != UnloadEventPolicyNone)
ggaren@apple.com7a176e12015-11-12 01:48:27 +0000526 dispatchUnloadEvents(unloadEventPolicy);
darinc370e7e2006-11-08 05:52:27 +0000527
darin@apple.com4d9d7182009-09-23 00:38:04 +0000528 m_isComplete = true; // to avoid calling completed() in finishedParsing()
ggarena57755c2007-07-09 21:08:10 +0000529 m_didCallImplicitClose = true; // don't want that one either
darinc370e7e2006-11-08 05:52:27 +0000530
akling@apple.com7f50aae2013-08-22 16:01:31 +0000531 if (m_frame.document() && m_frame.document()->parsing()) {
darinc370e7e2006-11-08 05:52:27 +0000532 finishedParsing();
akling@apple.com7f50aae2013-08-22 16:01:31 +0000533 m_frame.document()->setParsing(false);
darinc370e7e2006-11-08 05:52:27 +0000534 }
abarth@webkit.org55d49da2011-06-20 23:32:54 +0000535
darin@apple.com389af862016-11-14 03:22:31 +0000536 if (auto* document = m_frame.document()) {
mark.lam@apple.com45beb072012-12-12 23:04:20 +0000537 // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here?
darin@apple.com389af862016-11-14 03:22:31 +0000538 DatabaseManager::singleton().stopDatabases(*document, nullptr);
darinc370e7e2006-11-08 05:52:27 +0000539 }
540
cdumez@apple.com2d8d6082018-02-27 21:47:57 +0000541 policyChecker().stopCheck();
542
ap@apple.com3f0a0a12010-06-24 23:58:36 +0000543 // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000544 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +0000545}
546
547void FrameLoader::stop()
548{
549 // http://bugs.webkit.org/show_bug.cgi?id=10854
550 // The frame's last ref may be removed and it will be deleted by checkCompleted().
akling@apple.comf8515982013-09-02 18:50:01 +0000551 Ref<Frame> protect(m_frame);
abarth@webkit.orgfd912902011-06-10 21:16:20 +0000552
akling@apple.com7f50aae2013-08-22 16:01:31 +0000553 if (DocumentParser* parser = m_frame.document()->parser()) {
abarth@webkit.orgfd912902011-06-10 21:16:20 +0000554 parser->stopParsing();
555 parser->finish();
556 }
darinc370e7e2006-11-08 05:52:27 +0000557}
558
commit-queue@webkit.org8772f672020-04-13 08:24:39 +0000559void FrameLoader::closeURL()
darinc370e7e2006-11-08 05:52:27 +0000560{
akling@apple.com672cb852013-08-22 20:27:27 +0000561 history().saveDocumentState();
stavila@adobe.comeb50d7c2014-12-17 10:14:32 +0000562
shihchieh_lee@apple.com501b37c2020-04-28 16:36:38 +0000563 RefPtr<Document> currentDocument = m_frame.document();
stavila@adobe.comeb50d7c2014-12-17 10:14:32 +0000564 UnloadEventPolicy unloadEventPolicy;
565 if (m_frame.page() && m_frame.page()->chrome().client().isSVGImageChromeClient()) {
566 // If this is the SVGDocument of an SVGImage, no need to dispatch events or recalcStyle.
567 unloadEventPolicy = UnloadEventPolicyNone;
568 } else {
cdumez@apple.com9265dfe2019-10-17 01:44:16 +0000569 // Should only send the pagehide event here if the current document exists and has not been placed in the back/forward cache.
570 unloadEventPolicy = currentDocument && currentDocument->backForwardCacheState() == Document::NotInBackForwardCache ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly;
stavila@adobe.comeb50d7c2014-12-17 10:14:32 +0000571 }
572
573 stopLoading(unloadEventPolicy);
beidson@apple.com212b7842009-09-03 00:55:18 +0000574
shihchieh_lee@apple.com501b37c2020-04-28 16:36:38 +0000575 if (currentDocument)
576 currentDocument->editor().clearUndoRedoOperations();
darinc370e7e2006-11-08 05:52:27 +0000577}
578
abarth@webkit.org55d49da2011-06-20 23:32:54 +0000579bool FrameLoader::didOpenURL()
darinc370e7e2006-11-08 05:52:27 +0000580{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000581 if (m_frame.navigationScheduler().redirectScheduledDuringLoad()) {
darinc370e7e2006-11-08 05:52:27 +0000582 // A redirect was scheduled before the document was created.
583 // This can happen when one frame changes another frame's location.
584 return false;
darin@apple.com0f88bda2009-04-02 00:30:50 +0000585 }
darinc370e7e2006-11-08 05:52:27 +0000586
akling@apple.com7f50aae2013-08-22 16:01:31 +0000587 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +0000588
589 m_isComplete = false;
ggarena57755c2007-07-09 21:08:10 +0000590 m_didCallImplicitClose = false;
darinc370e7e2006-11-08 05:52:27 +0000591
ap@webkit.orgfbfb0f92009-05-08 07:58:08 +0000592 // If we are still in the process of initializing an empty document then
593 // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
594 // since it may cause clients to attempt to render the frame.
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000595 if (!m_stateMachine.creatingInitialEmptyDocument()) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000596 DOMWindow* window = m_frame.document()->domWindow();
abarth@webkit.org13fe1e22012-08-16 22:29:48 +0000597 window->setStatus(String());
598 window->setDefaultStatus(String());
ap@webkit.orgfbfb0f92009-05-08 07:58:08 +0000599 }
darinc370e7e2006-11-08 05:52:27 +0000600
601 started();
602
603 return true;
604}
605
ap@webkit.orga0a19872008-02-05 09:34:18 +0000606void FrameLoader::didExplicitOpen()
darinc370e7e2006-11-08 05:52:27 +0000607{
608 m_isComplete = false;
ggarena57755c2007-07-09 21:08:10 +0000609 m_didCallImplicitClose = false;
darinc370e7e2006-11-08 05:52:27 +0000610
andersca@apple.com1752dba2007-12-14 22:06:50 +0000611 // Calling document.open counts as committing the first real document load.
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000612 if (!m_stateMachine.committedFirstRealDocumentLoad())
613 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
cdumez@apple.com0af95e32019-04-16 23:07:35 +0000614
cdumez@apple.comc59c42d2019-10-30 18:36:22 +0000615 if (auto* document = m_frame.document())
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000616 m_client->dispatchDidExplicitOpen(document->url(), document->contentType());
andersca@apple.com1752dba2007-12-14 22:06:50 +0000617
darinc370e7e2006-11-08 05:52:27 +0000618 // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
619 // from a subsequent window.document.open / window.document.write call.
dbates@webkit.orgef42d382010-01-25 19:20:06 +0000620 // Canceling redirection here works for all cases because document.open
darinc370e7e2006-11-08 05:52:27 +0000621 // implicitly precedes document.write.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000622 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +0000623}
624
darinc370e7e2006-11-08 05:52:27 +0000625
626void FrameLoader::cancelAndClear()
627{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000628 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +0000629
630 if (!m_isComplete)
631 closeURL();
632
akling@apple.com7f50aae2013-08-22 16:01:31 +0000633 clear(m_frame.document(), false);
634 m_frame.script().updatePlatformScriptObjects();
darinc370e7e2006-11-08 05:52:27 +0000635}
636
aestes@apple.com408782b2016-11-29 18:40:55 +0000637static inline bool shouldClearWindowName(const Frame& frame, const Document& newDocument)
638{
639 if (!frame.isMainFrame())
640 return false;
641
642 if (frame.loader().opener())
643 return false;
644
akling@apple.com6be0e972017-01-18 19:35:49 +0000645 return !newDocument.securityOrigin().isSameOriginAs(frame.document()->securityOrigin());
aestes@apple.com408782b2016-11-29 18:40:55 +0000646}
647
beidson@apple.comdc5cfa42019-07-01 20:29:20 +0000648void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView, WTF::Function<void()>&& handleDOMWindowCreation)
darinc370e7e2006-11-08 05:52:27 +0000649{
beidson@apple.comdc5cfa42019-07-01 20:29:20 +0000650 bool neededClear = m_needsClear;
darinc370e7e2006-11-08 05:52:27 +0000651 m_needsClear = false;
beidson@apple.comdc5cfa42019-07-01 20:29:20 +0000652
cdumez@apple.com9265dfe2019-10-17 01:44:16 +0000653 if (neededClear && m_frame.document()->backForwardCacheState() != Document::InBackForwardCache) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000654 m_frame.document()->cancelParsing();
655 m_frame.document()->stopActiveDOMObjects();
timothy_horton@apple.com70d58d82014-07-26 18:45:04 +0000656 bool hadLivingRenderTree = m_frame.document()->hasLivingRenderTree();
shihchieh_lee@apple.com501b37c2020-04-28 16:36:38 +0000657 m_frame.document()->willBeRemovedFromFrame();
timothy_horton@apple.com70d58d82014-07-26 18:45:04 +0000658 if (hadLivingRenderTree)
simon.fraser@apple.com87cf1662018-09-08 20:19:22 +0000659 m_frame.document()->adjustFocusedNodeOnNodeRemoval(*m_frame.document());
darinc370e7e2006-11-08 05:52:27 +0000660 }
661
beidson@apple.comdc5cfa42019-07-01 20:29:20 +0000662 if (handleDOMWindowCreation)
663 handleDOMWindowCreation();
664
665 if (!neededClear)
666 return;
667
darinc370e7e2006-11-08 05:52:27 +0000668 // Do this after detaching the document so that the unload event works.
thatchera1e24df2007-09-14 23:53:29 +0000669 if (clearWindowProperties) {
commit-queue@webkit.org8599a762016-11-01 21:42:51 +0000670 InspectorInstrumentation::frameWindowDiscarded(m_frame, m_frame.document()->domWindow());
commit-queue@webkit.org8af5d212015-12-01 01:55:43 +0000671 m_frame.document()->domWindow()->resetUnlessSuspendedForDocumentSuspension();
cdumez@apple.com9265dfe2019-10-17 01:44:16 +0000672 m_frame.windowProxy().clearJSWindowProxiesNotMatchingDOMWindow(newDocument->domWindow(), m_frame.document()->backForwardCacheState() == Document::AboutToEnterBackForwardCache);
aestes@apple.com408782b2016-11-29 18:40:55 +0000673
674 if (shouldClearWindowName(m_frame, *newDocument))
utatane.tea@gmail.comc4579a02017-07-07 04:42:04 +0000675 m_frame.tree().setName(nullAtom());
weinigf9307632007-07-18 05:40:54 +0000676 }
darinc370e7e2006-11-08 05:52:27 +0000677
achristensen@apple.com09e70aa2017-04-27 16:42:13 +0000678 m_frame.eventHandler().clear();
bfulgham@apple.com46bde7c2016-04-07 21:15:34 +0000679
akling@apple.com7f50aae2013-08-22 16:01:31 +0000680 if (clearFrameView && m_frame.view())
681 m_frame.view()->clear();
eric@webkit.org0683d942008-08-06 10:01:35 +0000682
eric@webkit.org0683d942008-08-06 10:01:35 +0000683 // Do not drop the document before the ScriptController and view are cleared
684 // as some destructors might still try to access the document.
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +0000685 m_frame.setDocument(nullptr);
darinc370e7e2006-11-08 05:52:27 +0000686
akling@apple.com7f81b1e2013-09-06 17:23:03 +0000687 subframeLoader().clear();
eric@webkit.org0683d942008-08-06 10:01:35 +0000688
bfulgham@apple.com472a0342017-01-04 22:35:44 +0000689 if (clearWindowProperties)
cdumez@apple.com87a798a2018-04-19 04:02:30 +0000690 m_frame.windowProxy().setDOMWindow(newDocument->domWindow());
bfulgham@apple.com472a0342017-01-04 22:35:44 +0000691
antti90500a32007-09-27 23:56:17 +0000692 if (clearScriptObjects)
akling@apple.com7f50aae2013-08-22 16:01:31 +0000693 m_frame.script().clearScriptObjects();
eric@webkit.org0683d942008-08-06 10:01:35 +0000694
akling@apple.com7f50aae2013-08-22 16:01:31 +0000695 m_frame.script().enableEval();
abarth@webkit.org9d220b62012-06-09 19:35:02 +0000696
akling@apple.com7f50aae2013-08-22 16:01:31 +0000697 m_frame.navigationScheduler().clear();
darinc370e7e2006-11-08 05:52:27 +0000698
darin@apple.comf53381b2009-09-23 23:27:01 +0000699 m_checkTimer.stop();
700 m_shouldCallCheckCompleted = false;
701 m_shouldCallCheckLoadComplete = false;
abarth@webkit.org91289c32010-04-12 04:54:55 +0000702
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000703 if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad())
704 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
darinc370e7e2006-11-08 05:52:27 +0000705}
706
707void FrameLoader::receivedFirstData()
708{
commit-queue@webkit.orgc7d40872020-03-31 19:56:26 +0000709 auto protectedFrame = makeRef(m_frame);
710
achristensen@apple.come0301a32020-02-07 23:30:29 +0000711 dispatchDidCommitLoad(WTF::nullopt, WTF::nullopt);
jcivelli@chromium.org4b94add2011-11-19 08:45:01 +0000712 dispatchDidClearWindowObjectsInAllWorlds();
beidson@apple.com2a75a962012-04-24 18:12:55 +0000713 dispatchGlobalObjectAvailableInAllWorlds();
jcivelli@chromium.org4b94add2011-11-19 08:45:01 +0000714
darin8207db42007-02-20 18:18:39 +0000715 if (!m_documentLoader)
716 return;
abarth@webkit.org55d49da2011-06-20 23:32:54 +0000717
dbates@webkit.org66024662018-02-03 04:53:47 +0000718 auto& documentLoader = *m_documentLoader;
719 auto& title = documentLoader.title();
720 if (!title.string.isNull())
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000721 m_client->dispatchDidReceiveTitle(title);
dbates@webkit.org66024662018-02-03 04:53:47 +0000722
darin@apple.comc04189e2017-01-18 05:17:17 +0000723 ASSERT(m_frame.document());
724 auto& document = *m_frame.document();
725
dbates@webkit.org66024662018-02-03 04:53:47 +0000726 LinkLoader::loadLinksFromHeader(documentLoader.response().httpHeaderField(HTTPHeaderName::Link), document.url(), document, LinkLoader::MediaAttributeCheck::MediaAttributeEmpty);
yoav@yoav.ws1c12d5c2017-01-19 07:13:54 +0000727
abarth@webkit.org55d49da2011-06-20 23:32:54 +0000728 double delay;
darin@apple.com47a20cb2014-04-27 16:06:27 +0000729 String urlString;
cdumez@apple.com63b7fdd2019-09-12 04:32:29 +0000730 if (!parseMetaHTTPEquivRefresh(documentLoader.response().httpHeaderField(HTTPHeaderName::Refresh), delay, urlString))
ape9991d52006-12-08 18:19:51 +0000731 return;
darin@apple.comc04189e2017-01-18 05:17:17 +0000732 auto completedURL = urlString.isEmpty() ? document.url() : document.completeURL(urlString);
commit-queue@webkit.org39359f02020-04-25 21:28:45 +0000733 if (!completedURL.protocolIsJavaScript())
darin@apple.comc04189e2017-01-18 05:17:17 +0000734 m_frame.navigationScheduler().scheduleRedirect(document, delay, completedURL);
ddkilzer@apple.com70f15392014-04-01 19:21:34 +0000735 else {
darin@apple.comc04189e2017-01-18 05:17:17 +0000736 auto message = "Refused to refresh " + document.url().stringCenterEllipsizedToLength() + " to a javascript: URL";
dbates@webkit.org66024662018-02-03 04:53:47 +0000737 document.addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
ddkilzer@apple.com70f15392014-04-01 19:21:34 +0000738 }
darinc370e7e2006-11-08 05:52:27 +0000739}
740
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000741void FrameLoader::setOutgoingReferrer(const URL& url)
japhet@chromium.orgb254c9b2011-01-26 19:14:26 +0000742{
levin@chromium.org1a2fef42011-03-01 02:10:28 +0000743 m_outgoingReferrer = url.strippedForUseAsReferrer();
abarth@webkit.org412c54e2010-04-20 22:12:16 +0000744}
abarth@webkit.org91289c32010-04-12 04:54:55 +0000745
dbates@webkit.org123b1af2019-09-23 21:56:43 +0000746void FrameLoader::didBeginDocument(bool dispatch)
abarth@webkit.org412c54e2010-04-20 22:12:16 +0000747{
748 m_needsClear = true;
749 m_isComplete = false;
750 m_didCallImplicitClose = false;
akling@apple.com7f50aae2013-08-22 16:01:31 +0000751 m_frame.document()->setReadyState(Document::Loading);
abarth@webkit.org91289c32010-04-12 04:54:55 +0000752
753 if (m_pendingStateObject) {
darin@apple.com961f2a52016-12-31 09:51:29 +0000754 m_frame.document()->statePopped(*m_pendingStateObject);
cdumez@apple.comd839ea12015-07-04 19:42:18 +0000755 m_pendingStateObject = nullptr;
abarth@webkit.org91289c32010-04-12 04:54:55 +0000756 }
abarth@webkit.org91289c32010-04-12 04:54:55 +0000757
andersca@apple.com6c6fb4b2009-08-12 22:03:02 +0000758 if (dispatch)
aroben@apple.com11dd5262009-11-13 23:49:05 +0000759 dispatchDidClearWindowObjectsInAllWorlds();
abarth@webkit.org412c54e2010-04-20 22:12:16 +0000760
abarth@webkit.org622d9df2009-05-22 16:44:47 +0000761 updateFirstPartyForCookies();
dbates@webkit.org123b1af2019-09-23 21:56:43 +0000762 m_frame.document()->initContentSecurityPolicy();
darinc370e7e2006-11-08 05:52:27 +0000763
akling@apple.com1c29edbc2013-08-23 23:19:21 +0000764 const Settings& settings = m_frame.settings();
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +0000765 m_frame.document()->cachedResourceLoader().setImagesEnabled(settings.areImagesEnabled());
766 m_frame.document()->cachedResourceLoader().setAutoLoadImages(settings.loadsImagesAutomatically());
aroben@apple.com3adf2452008-02-07 23:19:31 +0000767
collinj@webkit.org9c672f62008-09-19 04:15:14 +0000768 if (m_documentLoader) {
andersca@apple.com30391b42014-06-16 19:26:49 +0000769 String dnsPrefetchControl = m_documentLoader->response().httpHeaderField(HTTPHeaderName::XDNSPrefetchControl);
collinj@webkit.org9c672f62008-09-19 04:15:14 +0000770 if (!dnsPrefetchControl.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000771 m_frame.document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
jochen@chromium.orgadec40f2011-02-09 17:03:38 +0000772
dbates@webkit.org41f504e2018-05-07 17:52:34 +0000773 m_frame.document()->contentSecurityPolicy()->didReceiveHeaders(ContentSecurityPolicyResponseHeaders(m_documentLoader->response()), referrer(), ContentSecurityPolicy::ReportParsingErrors::No);
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +0000774
cdumez@apple.com7c12c6c2018-05-30 21:30:21 +0000775 String referrerPolicy = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ReferrerPolicy);
776 if (!referrerPolicy.isNull())
777 m_frame.document()->processReferrerPolicy(referrerPolicy, ReferrerPolicySource::HTTPHeader);
778
andersca@apple.com30391b42014-06-16 19:26:49 +0000779 String headerContentLanguage = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ContentLanguage);
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +0000780 if (!headerContentLanguage.isEmpty()) {
781 size_t commaIndex = headerContentLanguage.find(',');
782 headerContentLanguage.truncate(commaIndex); // notFound == -1 == don't truncate
darin@apple.com940b9ea2017-11-25 02:44:45 +0000783 headerContentLanguage = stripLeadingAndTrailingHTMLSpaces(headerContentLanguage);
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +0000784 if (!headerContentLanguage.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000785 m_frame.document()->setContentLanguage(headerContentLanguage);
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +0000786 }
collinj@webkit.org9c672f62008-09-19 04:15:14 +0000787 }
788
akling@apple.com672cb852013-08-22 20:27:27 +0000789 history().restoreDocumentState();
darinc370e7e2006-11-08 05:52:27 +0000790}
791
darinc370e7e2006-11-08 05:52:27 +0000792void FrameLoader::finishedParsing()
793{
simon.fraser@apple.com677f0422017-12-02 17:55:24 +0000794 LOG(Loading, "WebCoreLoading %s: Finished parsing", m_frame.tree().uniqueName().string().utf8().data());
795
commit-queue@webkit.org11fed0a2020-04-04 00:44:31 +0000796 m_frame.injectUserScripts(UserScriptInjectionTime::DocumentEnd);
aestes@apple.come35644e2011-04-07 20:23:48 +0000797
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000798 if (m_stateMachine.creatingInitialEmptyDocument())
mjs8d620d52007-05-10 12:31:42 +0000799 return;
800
darinc370e7e2006-11-08 05:52:27 +0000801 // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
802 // because doing so will cause us to re-enter the destructor when protector goes out of scope.
beidson@apple.comf7eea402008-07-10 04:51:10 +0000803 // Null-checking the FrameView indicates whether or not we're in the destructor.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000804 RefPtr<Frame> protector = m_frame.view() ? &m_frame : 0;
darinc370e7e2006-11-08 05:52:27 +0000805
youenn@apple.comee96d0f2020-03-18 13:59:23 +0000806 m_client->dispatchDidFinishDocumentLoad();
darin@chromium.org1750e242008-12-08 18:13:25 +0000807
cdumez@apple.com6d7c65e2015-09-02 17:07:57 +0000808 scrollToFragmentWithParentBoundary(m_frame.document()->url());
809
darinc370e7e2006-11-08 05:52:27 +0000810 checkCompleted();
811
akling@apple.com7f50aae2013-08-22 16:01:31 +0000812 if (!m_frame.view())
darinc370e7e2006-11-08 05:52:27 +0000813 return; // We are being destroyed by something checkCompleted called.
814
815 // Check if the scrollbars are really needed for the content.
816 // If not, remove them, relayout, and repaint.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000817 m_frame.view()->restoreScrollbar();
darinc370e7e2006-11-08 05:52:27 +0000818}
819
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +0000820void FrameLoader::loadDone(LoadCompletionType type)
darinc370e7e2006-11-08 05:52:27 +0000821{
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +0000822 if (type == LoadCompletionType::Finish)
823 checkCompleted();
824 else
825 scheduleCheckCompleted();
826}
827
828void FrameLoader::subresourceLoadDone(LoadCompletionType type)
829{
830 if (type == LoadCompletionType::Finish)
831 checkLoadComplete();
832 else
833 scheduleCheckLoadComplete();
darinc370e7e2006-11-08 05:52:27 +0000834}
835
commit-queue@webkit.org87bc9132020-09-12 08:35:27 +0000836bool FrameLoader::preventsParentFromBeingComplete(const Frame& frame) const
837{
838 return !frame.loader().m_isComplete && (!frame.ownerElement() || !frame.ownerElement()->isLazyLoadObserverActive());
839}
840
darin@apple.com4d9d7182009-09-23 00:38:04 +0000841bool FrameLoader::allChildrenAreComplete() const
842{
darin@apple.comfed4d162013-08-25 02:28:06 +0000843 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
commit-queue@webkit.org87bc9132020-09-12 08:35:27 +0000844 if (preventsParentFromBeingComplete(*child))
darin@apple.com4d9d7182009-09-23 00:38:04 +0000845 return false;
846 }
847 return true;
848}
849
darin@apple.comf53381b2009-09-23 23:27:01 +0000850bool FrameLoader::allAncestorsAreComplete() const
851{
darin@apple.comfed4d162013-08-25 02:28:06 +0000852 for (Frame* ancestor = &m_frame; ancestor; ancestor = ancestor->tree().parent()) {
andersca@apple.comdf550b92013-08-15 22:17:17 +0000853 if (!ancestor->loader().m_isComplete)
darin@apple.comf53381b2009-09-23 23:27:01 +0000854 return false;
855 }
856 return true;
857}
858
darinc370e7e2006-11-08 05:52:27 +0000859void FrameLoader::checkCompleted()
860{
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +0000861 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
darin@apple.comf53381b2009-09-23 23:27:01 +0000862 m_shouldCallCheckCompleted = false;
863
darinc370e7e2006-11-08 05:52:27 +0000864 // Have we completed before?
865 if (m_isComplete)
866 return;
867
antti@apple.com079cbf52017-05-05 18:39:30 +0000868 // FIXME: It would be better if resource loads were kicked off after render tree update (or didn't complete synchronously).
869 // https://bugs.webkit.org/show_bug.cgi?id=171729
870 if (m_frame.document()->inRenderTreeUpdate()) {
871 scheduleCheckCompleted();
872 return;
873 }
874
darinc370e7e2006-11-08 05:52:27 +0000875 // Are we still parsing?
akling@apple.com7f50aae2013-08-22 16:01:31 +0000876 if (m_frame.document()->parsing())
darinc370e7e2006-11-08 05:52:27 +0000877 return;
878
879 // Still waiting for images/scripts?
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +0000880 if (m_frame.document()->cachedResourceLoader().requestCount())
ap@webkit.orgf9b6eff2009-02-10 17:33:33 +0000881 return;
darinc370e7e2006-11-08 05:52:27 +0000882
eric.carlson@apple.com9c7fc722010-08-26 16:45:43 +0000883 // Still waiting for elements that don't go through a FrameLoader?
akling@apple.com7f50aae2013-08-22 16:01:31 +0000884 if (m_frame.document()->isDelayingLoadEvent())
eric.carlson@apple.com9c7fc722010-08-26 16:45:43 +0000885 return;
886
antti@apple.com9f4e3b22017-02-19 12:12:07 +0000887 auto* scriptableParser = m_frame.document()->scriptableDocumentParser();
888 if (scriptableParser && scriptableParser->hasScriptsWaitingForStylesheets())
889 return;
890
andreas.kling@nokia.com01f92442011-02-28 13:46:06 +0000891 // Any frame that hasn't completed yet?
892 if (!allChildrenAreComplete())
893 return;
894
darin@apple.comc2843002014-04-25 06:01:34 +0000895 // Important not to protect earlier in this function, because earlier parts
darin@apple.comfe9effd2014-04-25 06:02:42 +0000896 // of this function can be called in the frame's destructor, and it's not legal
darin@apple.comc2843002014-04-25 06:01:34 +0000897 // to ref an object while it's being destroyed.
898 Ref<Frame> protect(m_frame);
899
darinc370e7e2006-11-08 05:52:27 +0000900 // OK, completed.
901 m_isComplete = true;
cdumez@apple.comd839ea12015-07-04 19:42:18 +0000902 m_requestedHistoryItem = nullptr;
akling@apple.com7f50aae2013-08-22 16:01:31 +0000903 m_frame.document()->setReadyState(Document::Complete);
darinc370e7e2006-11-08 05:52:27 +0000904
ggarena57755c2007-07-09 21:08:10 +0000905 checkCallImplicitClose(); // if we didn't do it before
darinc370e7e2006-11-08 05:52:27 +0000906
akling@apple.com7f50aae2013-08-22 16:01:31 +0000907 m_frame.navigationScheduler().startTimer();
darinc370e7e2006-11-08 05:52:27 +0000908
909 completed();
akling@apple.com7f50aae2013-08-22 16:01:31 +0000910 if (m_frame.page())
mjs8d620d52007-05-10 12:31:42 +0000911 checkLoadComplete();
darinc370e7e2006-11-08 05:52:27 +0000912}
913
andersca@apple.com574a7452014-11-21 20:10:13 +0000914void FrameLoader::checkTimerFired()
weinigc34c71c2007-03-09 16:05:37 +0000915{
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +0000916 checkCompletenessNow();
917}
918
919void FrameLoader::checkCompletenessNow()
920{
akling@apple.comf8515982013-09-02 18:50:01 +0000921 Ref<Frame> protect(m_frame);
commit-queue@webkit.org667ee8b2012-02-08 02:21:04 +0000922
akling@apple.com7f50aae2013-08-22 16:01:31 +0000923 if (Page* page = m_frame.page()) {
darin@apple.comf53381b2009-09-23 23:27:01 +0000924 if (page->defersLoading())
925 return;
926 }
927 if (m_shouldCallCheckCompleted)
928 checkCompleted();
929 if (m_shouldCallCheckLoadComplete)
930 checkLoadComplete();
931}
932
933void FrameLoader::startCheckCompleteTimer()
934{
935 if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
936 return;
937 if (m_checkTimer.isActive())
938 return;
cdumez@apple.combc919b02017-04-09 14:49:14 +0000939 m_checkTimer.startOneShot(0_s);
weinigc34c71c2007-03-09 16:05:37 +0000940}
941
942void FrameLoader::scheduleCheckCompleted()
943{
darin@apple.comf53381b2009-09-23 23:27:01 +0000944 m_shouldCallCheckCompleted = true;
945 startCheckCompleteTimer();
beidson398923b2007-07-31 20:29:02 +0000946}
947
948void FrameLoader::scheduleCheckLoadComplete()
949{
darin@apple.comf53381b2009-09-23 23:27:01 +0000950 m_shouldCallCheckLoadComplete = true;
951 startCheckCompleteTimer();
beidson398923b2007-07-31 20:29:02 +0000952}
953
ggarena57755c2007-07-09 21:08:10 +0000954void FrameLoader::checkCallImplicitClose()
darinc370e7e2006-11-08 05:52:27 +0000955{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000956 if (m_didCallImplicitClose || m_frame.document()->parsing() || m_frame.document()->isDelayingLoadEvent())
darinc370e7e2006-11-08 05:52:27 +0000957 return;
958
darin@apple.com4d9d7182009-09-23 00:38:04 +0000959 if (!allChildrenAreComplete())
960 return; // still got a frame running -> too early
darinc370e7e2006-11-08 05:52:27 +0000961
ggarena57755c2007-07-09 21:08:10 +0000962 m_didCallImplicitClose = true;
darinc370e7e2006-11-08 05:52:27 +0000963 m_wasUnloadEventEmitted = false;
akling@apple.com7f50aae2013-08-22 16:01:31 +0000964 m_frame.document()->implicitClose();
darinc370e7e2006-11-08 05:52:27 +0000965}
966
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000967void FrameLoader::loadURLIntoChildFrame(const URL& url, const String& referer, Frame* childFrame)
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000968{
krollin@apple.combdeaed72020-01-08 01:31:20 +0000969 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadURLIntoChildFrame: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +0000970
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000971 ASSERT(childFrame);
darin@apple.coma7e141f2009-03-06 17:22:07 +0000972
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +0000973#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
darin@apple.com961f2a52016-12-31 09:51:29 +0000974 if (auto activeLoader = activeDocumentLoader()) {
975 if (auto subframeArchive = activeLoader->popArchiveForSubframe(childFrame->tree().uniqueName(), url)) {
976 childFrame->loader().loadArchive(RefPtr<Archive> { subframeArchive }.releaseNonNull());
977 return;
978 }
mihaip@chromium.orge5dbd372010-12-08 02:32:41 +0000979 }
darin@apple.com961f2a52016-12-31 09:51:29 +0000980#endif
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000981
darin@apple.coma7e141f2009-03-06 17:22:07 +0000982 // If we're moving in the back/forward list, we might want to replace the content
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000983 // of this child frame with whatever was there at that point.
darin@apple.com961f2a52016-12-31 09:51:29 +0000984 auto* parentItem = history().currentItem();
985 if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType()) && !m_frame.document()->loadEventFinished()) {
986 if (auto* childItem = parentItem->childItemWithTarget(childFrame->tree().uniqueName())) {
ap@apple.com4d286a92013-08-19 23:41:18 +0000987 childFrame->loader().m_requestedHistoryItem = childItem;
cdumez@apple.com29f7c1e2019-03-13 20:32:48 +0000988 childFrame->loader().loadDifferentDocumentItem(*childItem, nullptr, loadType(), MayAttemptCacheOnlyLoadForFormSubmissionItem, ShouldTreatAsContinuingLoad::No);
mihaip@chromium.orge5dbd372010-12-08 02:32:41 +0000989 return;
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000990 }
991 }
992
beidson@apple.com7034ec72017-07-06 00:01:53 +0000993 auto* lexicalFrame = lexicalFrameFromCommonVM();
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +0000994 auto initiatedByMainFrame = lexicalFrame && lexicalFrame->isMainFrame() ? InitiatedByMainFrame::Yes : InitiatedByMainFrame::Unknown;
beidson@apple.com7034ec72017-07-06 00:01:53 +0000995
commit-queue@webkit.org1b6bd842020-04-18 17:04:07 +0000996 FrameLoadRequest frameLoadRequest { *m_frame.document(), m_frame.document()->securityOrigin(), { url }, "_self"_s, initiatedByMainFrame };
997 frameLoadRequest.setNewFrameOpenerPolicy(NewFrameOpenerPolicy::Suppress);
998 frameLoadRequest.setLockBackForwardList(LockBackForwardList::Yes);
wilander@apple.com6ffdf8f2019-02-06 22:02:15 +0000999 childFrame->loader().loadURL(WTFMove(frameLoadRequest), referer, FrameLoadType::RedirectWithLockedBackForwardList, nullptr, { }, WTF::nullopt, [] { });
beidson@apple.com47ef96f2015-05-29 16:38:13 +00001000}
beidson@apple.comf36a4a12008-03-25 17:11:16 +00001001
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +00001002#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
darin@apple.com961f2a52016-12-31 09:51:29 +00001003
1004void FrameLoader::loadArchive(Ref<Archive>&& archive)
beidson@apple.comf36a4a12008-03-25 17:11:16 +00001005{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001006 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadArchive: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001007
japhet@chromium.orgac5cd4b2012-04-12 19:27:28 +00001008 ArchiveResource* mainResource = archive->mainResource();
beidson@apple.comf36a4a12008-03-25 17:11:16 +00001009 ASSERT(mainResource);
1010 if (!mainResource)
1011 return;
beidson@apple.comceb7cba2015-05-19 22:22:51 +00001012
jh718.park@samsung.com9f99af52016-03-15 00:22:45 +00001013 ResourceResponse response(URL(), mainResource->mimeType(), mainResource->data().size(), mainResource->textEncoding());
1014 SubstituteData substituteData(&mainResource->data(), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
beidson@apple.comf36a4a12008-03-25 17:11:16 +00001015
1016 ResourceRequest request(mainResource->url());
beidson@apple.comf36a4a12008-03-25 17:11:16 +00001017
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001018 auto documentLoader = m_client->createDocumentLoader(request, substituteData);
darin@apple.com961f2a52016-12-31 09:51:29 +00001019 documentLoader->setArchive(WTFMove(archive));
achristensen@apple.com10e4a7b2018-11-28 21:14:43 +00001020 load(documentLoader.get());
beidson@apple.comf36a4a12008-03-25 17:11:16 +00001021}
darin@apple.com961f2a52016-12-31 09:51:29 +00001022
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +00001023#endif // ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
beidson@apple.comf36a4a12008-03-25 17:11:16 +00001024
darinc370e7e2006-11-08 05:52:27 +00001025String FrameLoader::outgoingReferrer() const
1026{
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001027 // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
1028 // for why we walk the parent chain for srcdoc documents.
akling@apple.com7f50aae2013-08-22 16:01:31 +00001029 Frame* frame = &m_frame;
antti@apple.com1f5a2462016-12-14 18:54:28 +00001030 while (frame && frame->document()->isSrcdocDocument()) {
darin@apple.comfed4d162013-08-25 02:28:06 +00001031 frame = frame->tree().parent();
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001032 // Srcdoc documents cannot be top-level documents, by definition,
1033 // because they need to be contained in iframes with the srcdoc.
1034 ASSERT(frame);
1035 }
antti@apple.com1f5a2462016-12-14 18:54:28 +00001036 if (!frame)
1037 return emptyString();
andersca@apple.comdf550b92013-08-15 22:17:17 +00001038 return frame->loader().m_outgoingReferrer;
darinc370e7e2006-11-08 05:52:27 +00001039}
1040
cdumez@apple.com1f985b82020-05-01 23:07:38 +00001041String FrameLoader::outgoingOrigin() const
1042{
1043 return m_frame.document()->securityOrigin().toString();
1044}
1045
dbates@webkit.org28db74a2016-04-15 22:23:44 +00001046bool FrameLoader::checkIfFormActionAllowedByCSP(const URL& url, bool didReceiveRedirectResponse) const
commit-queue@webkit.org78e860e2012-08-16 12:42:09 +00001047{
1048 if (m_submittedFormURL.isEmpty())
1049 return true;
1050
dbates@webkit.org28db74a2016-04-15 22:23:44 +00001051 auto redirectResponseReceived = didReceiveRedirectResponse ? ContentSecurityPolicy::RedirectResponseReceived::Yes : ContentSecurityPolicy::RedirectResponseReceived::No;
commit-queue@webkit.org03af1952016-09-22 08:28:37 +00001052 return m_frame.document()->contentSecurityPolicy()->allowFormAction(url, redirectResponseReceived);
commit-queue@webkit.org78e860e2012-08-16 12:42:09 +00001053}
1054
darinc370e7e2006-11-08 05:52:27 +00001055void FrameLoader::setOpener(Frame* opener)
1056{
creis@chromium.org16d76c72012-12-04 17:39:26 +00001057 if (m_opener && !opener)
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001058 m_client->didDisownOpener();
creis@chromium.org16d76c72012-12-04 17:39:26 +00001059
rniwa@webkit.org2c6d4eb2017-07-01 21:26:31 +00001060 if (m_opener) {
1061 // When setOpener is called in ~FrameLoader, opener's m_frameLoader is already cleared.
1062 auto& openerFrameLoader = m_opener == &m_frame ? *this : m_opener->loader();
achristensen@apple.com2ace43d2020-11-05 16:54:48 +00001063 openerFrameLoader.m_openedFrames.remove(m_frame);
rniwa@webkit.org2c6d4eb2017-07-01 21:26:31 +00001064 }
cdumez@apple.com2e472362018-12-01 22:40:07 +00001065 if (opener) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00001066 opener->loader().m_openedFrames.add(&m_frame);
cdumez@apple.com2e472362018-12-01 22:40:07 +00001067 if (auto* page = m_frame.page())
1068 page->setOpenedByDOMWithOpener();
1069 }
achristensen@apple.com2ace43d2020-11-05 16:54:48 +00001070 m_opener = makeWeakPtr(opener);
weinig343b6ff2007-08-07 03:08:53 +00001071
akling@apple.com7f50aae2013-08-22 16:01:31 +00001072 if (m_frame.document())
1073 m_frame.document()->initSecurityContext();
darinc370e7e2006-11-08 05:52:27 +00001074}
1075
darinc370e7e2006-11-08 05:52:27 +00001076void FrameLoader::provisionalLoadStarted()
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00001077{
1078 if (m_stateMachine.firstLayoutDone())
1079 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
achristensen@apple.com6fddc912018-10-18 21:16:52 +00001080 m_frame.navigationScheduler().cancel(NewLoadInProgress::Yes);
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001081 m_client->provisionalLoadStarted();
cdumez@apple.comef2c0152017-01-13 17:54:53 +00001082
1083 if (m_frame.isMainFrame()) {
sbarati@apple.comce7ec112018-04-17 15:57:32 +00001084 tracePoint(MainResourceLoadDidStartProvisional);
simon.fraser@apple.com83325b92017-03-17 00:47:16 +00001085
cdumez@apple.comef2c0152017-01-13 17:54:53 +00001086 if (auto* page = m_frame.page())
1087 page->didStartProvisionalLoad();
1088 }
darinc370e7e2006-11-08 05:52:27 +00001089}
1090
darinc370e7e2006-11-08 05:52:27 +00001091void FrameLoader::resetMultipleFormSubmissionProtection()
1092{
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001093 m_submittedFormURL = URL();
darinc370e7e2006-11-08 05:52:27 +00001094}
1095
abarth@webkit.org622d9df2009-05-22 16:44:47 +00001096void FrameLoader::updateFirstPartyForCookies()
darinc370e7e2006-11-08 05:52:27 +00001097{
darin@apple.comfed4d162013-08-25 02:28:06 +00001098 if (m_frame.tree().parent())
1099 setFirstPartyForCookies(m_frame.tree().parent()->document()->firstPartyForCookies());
darinc370e7e2006-11-08 05:52:27 +00001100 else
akling@apple.com7f50aae2013-08-22 16:01:31 +00001101 setFirstPartyForCookies(m_frame.document()->url());
darinc370e7e2006-11-08 05:52:27 +00001102}
1103
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001104void FrameLoader::setFirstPartyForCookies(const URL& url)
darinc370e7e2006-11-08 05:52:27 +00001105{
darin@apple.comfed4d162013-08-25 02:28:06 +00001106 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
darin@apple.comaf8b1a92011-06-25 00:09:37 +00001107 frame->document()->setFirstPartyForCookies(url);
dbates@webkit.org8c917f22018-04-24 07:36:59 +00001108
cdumez@apple.com0b8674fb2019-03-13 19:53:41 +00001109 RegistrableDomain registrableDomain(url);
dbates@webkit.org8c917f22018-04-24 07:36:59 +00001110 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame)) {
cdumez@apple.com0b8674fb2019-03-13 19:53:41 +00001111 if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(frame->document()->url()) || registrableDomain.matches(frame->document()->url()))
dbates@webkit.org940f0b82018-07-24 16:27:25 +00001112 frame->document()->setSiteForCookies(url);
dbates@webkit.org8c917f22018-04-24 07:36:59 +00001113 }
darinc370e7e2006-11-08 05:52:27 +00001114}
1115
darin@apple.comd69216d2008-03-11 00:45:47 +00001116// This does the same kind of work that didOpenURL does, except it relies on the fact
darinc370e7e2006-11-08 05:52:27 +00001117// that a higher level already checked that the URLs match and the scrolling is the right thing to do.
darin@apple.com961f2a52016-12-31 09:51:29 +00001118void FrameLoader::loadInSameDocument(const URL& url, SerializedScriptValue* stateObject, bool isNewNavigation)
darinc370e7e2006-11-08 05:52:27 +00001119{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001120 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadInSameDocument: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001121
beidson@apple.com08c61752009-12-03 19:04:40 +00001122 // If we have a state object, we cannot also be a new navigation.
1123 ASSERT(!stateObject || (stateObject && !isNewNavigation));
1124
1125 // Update the data source's request with the new URL to fake the URL change
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001126 URL oldURL = m_frame.document()->url();
akling@apple.com7f50aae2013-08-22 16:01:31 +00001127 m_frame.document()->setURL(url);
jochen@chromium.org7495f962012-05-04 16:43:03 +00001128 setOutgoingReferrer(url);
beidson@apple.com08c61752009-12-03 19:04:40 +00001129 documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
1130 if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
1131 // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add
1132 // based on the current request. Must also happen before we openURL and displace the
1133 // scroll position, since adding the BF item will save away scroll state.
1134
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001135 // NB2: If we were loading a long, slow doc, and the user fragment navigated before
beidson@apple.com08c61752009-12-03 19:04:40 +00001136 // it was done, currItem is now set the that slow doc, and prevItem is whatever was
1137 // before it. Adding the b/f item will bump the slow doc down to prevItem, even
1138 // though its load is not yet done. I think this all works out OK, for one because
1139 // we have already saved away the scroll and doc state for the long slow load,
1140 // but it's not an obvious case.
1141
akling@apple.com672cb852013-08-22 20:27:27 +00001142 history().updateBackForwardListForFragmentScroll();
beidson@apple.com8127cdc2009-08-07 15:35:19 +00001143 }
darin@apple.com1e231d52020-04-25 18:01:55 +00001144
1145 bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && !equalRespectingNullity(url.fragmentIdentifier(), oldURL.fragmentIdentifier());
1146
akling@apple.com672cb852013-08-22 20:27:27 +00001147 history().updateForSameDocumentNavigation();
britto@apple.com195cc0b2008-07-23 16:48:47 +00001148
1149 // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
beidson@apple.com08c61752009-12-03 19:04:40 +00001150 if (hashChange)
akling@apple.com7f50aae2013-08-22 16:01:31 +00001151 m_frame.eventHandler().stopAutoscrollTimer();
beidson@apple.com08c61752009-12-03 19:04:40 +00001152
darinc370e7e2006-11-08 05:52:27 +00001153 // It's important to model this as a load that starts and immediately finishes.
1154 // Otherwise, the parent frame may think we never finished loading.
beidson@apple.com08c61752009-12-03 19:04:40 +00001155 started();
japhet@chromium.org48bb2602010-03-04 23:01:45 +00001156
dbates@webkit.org86a1c672018-08-10 17:39:53 +00001157 if (auto* ownerElement = m_frame.ownerElement()) {
1158 auto* ownerRenderer = ownerElement->renderer();
1159 auto* view = m_frame.view();
1160 if (is<RenderWidget>(ownerRenderer) && view)
1161 downcast<RenderWidget>(*ownerRenderer).setWidget(view);
1162 }
1163
japhet@chromium.org48bb2602010-03-04 23:01:45 +00001164 // We need to scroll to the fragment whether or not a hash change occurred, since
1165 // the user might have scrolled since the previous navigation.
simon.fraser@apple.comc79e4862017-03-08 20:01:15 +00001166 scrollToFragmentWithParentBoundary(url, isNewNavigation);
beidson@apple.com08c61752009-12-03 19:04:40 +00001167
darinc370e7e2006-11-08 05:52:27 +00001168 m_isComplete = false;
1169 checkCompleted();
beidson@apple.com08c61752009-12-03 19:04:40 +00001170
1171 if (isNewNavigation) {
1172 // This will clear previousItem from the rest of the frame tree that didn't
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001173 // doing any loading. We need to make a pass on this now, since for fragment
1174 // navigation we'll not go through a real load and reach Completed state.
beidson@apple.com08c61752009-12-03 19:04:40 +00001175 checkLoadComplete();
1176 }
1177
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001178 m_client->dispatchDidNavigateWithinPage();
darin@chromium.orgfe279962010-03-16 17:26:59 +00001179
darin@apple.com961f2a52016-12-31 09:51:29 +00001180 m_frame.document()->statePopped(stateObject ? Ref<SerializedScriptValue> { *stateObject } : SerializedScriptValue::nullValue());
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001181 m_client->dispatchDidPopStateWithinPage();
beidson@apple.com08c61752009-12-03 19:04:40 +00001182
1183 if (hashChange) {
commit-queue@webkit.org39359f02020-04-25 21:28:45 +00001184 m_frame.document()->enqueueHashchangeEvent(oldURL.string(), url.string());
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001185 m_client->dispatchDidChangeLocationWithinPage();
beidson@apple.com08c61752009-12-03 19:04:40 +00001186 }
1187
1188 // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001189 m_client->didFinishLoad();
darinc370e7e2006-11-08 05:52:27 +00001190}
1191
1192bool FrameLoader::isComplete() const
1193{
1194 return m_isComplete;
1195}
1196
darinc370e7e2006-11-08 05:52:27 +00001197void FrameLoader::completed()
1198{
akling@apple.comf8515982013-09-02 18:50:01 +00001199 Ref<Frame> protect(m_frame);
beidson@apple.coma5662512009-10-27 00:19:33 +00001200
darin@apple.comfed4d162013-08-25 02:28:06 +00001201 for (Frame* descendant = m_frame.tree().traverseNext(&m_frame); descendant; descendant = descendant->tree().traverseNext(&m_frame))
akling@apple.com9ce995f2013-08-21 20:54:20 +00001202 descendant->navigationScheduler().startTimer();
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001203
darin@apple.comfed4d162013-08-25 02:28:06 +00001204 if (Frame* parent = m_frame.tree().parent())
andersca@apple.comdf550b92013-08-15 22:17:17 +00001205 parent->loader().checkCompleted();
beidson@apple.coma5662512009-10-27 00:19:33 +00001206
akling@apple.com7f50aae2013-08-22 16:01:31 +00001207 if (m_frame.view())
mmaxfield@apple.com6ebeece2014-12-09 21:03:54 +00001208 m_frame.view()->maintainScrollPositionAtAnchor(nullptr);
darinc370e7e2006-11-08 05:52:27 +00001209}
1210
1211void FrameLoader::started()
1212{
darin@apple.comfed4d162013-08-25 02:28:06 +00001213 for (Frame* frame = &m_frame; frame; frame = frame->tree().parent())
andersca@apple.comdf550b92013-08-15 22:17:17 +00001214 frame->loader().m_isComplete = false;
darinc370e7e2006-11-08 05:52:27 +00001215}
1216
achristensen@apple.comc41ad692019-01-31 21:23:44 +00001217void FrameLoader::prepareForLoadStart()
darinc370e7e2006-11-08 05:52:27 +00001218{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001219 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "prepareForLoadStart: Starting frame load");
commit-queue@webkit.org6d635222016-03-08 06:44:59 +00001220
japhet@chromium.org7879dd72012-08-30 02:58:37 +00001221 m_progressTracker->progressStarted();
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001222 m_client->dispatchDidStartProvisionalLoad();
achristensen@apple.comc41ad692019-01-31 21:23:44 +00001223
1224 if (AXObjectCache::accessibilityEnabled()) {
1225 if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache()) {
1226 AXObjectCache::AXLoadingEvent loadingEvent = loadType() == FrameLoadType::Reload ? AXObjectCache::AXLoadingReloaded : AXObjectCache::AXLoadingStarted;
1227 cache->frameLoadingEventNotification(&m_frame, loadingEvent);
ossy@webkit.org451e9b02014-01-27 12:40:18 +00001228 }
achristensen@apple.comc41ad692019-01-31 21:23:44 +00001229 }
darinc370e7e2006-11-08 05:52:27 +00001230}
1231
1232void FrameLoader::setupForReplace()
1233{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001234 m_client->revertToProvisionalState(m_documentLoader.get());
darinc370e7e2006-11-08 05:52:27 +00001235 setState(FrameStateProvisional);
1236 m_provisionalDocumentLoader = m_documentLoader;
krollin@apple.combdeaed72020-01-08 01:31:20 +00001237 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "setupForReplace: Setting provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
cdumez@apple.comd839ea12015-07-04 19:42:18 +00001238 m_documentLoader = nullptr;
darinc370e7e2006-11-08 05:52:27 +00001239 detachChildren();
1240}
1241
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +00001242void FrameLoader::loadFrameRequest(FrameLoadRequest&& request, Event* event, RefPtr<FormState>&& formState, Optional<AdClickAttribution>&& adClickAttribution)
dbates@webkit.org29908522017-01-07 07:14:03 +00001243{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001244 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadFrameRequest: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001245
inferno@chromium.org670ab752011-07-13 18:51:44 +00001246 // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader.
darin@apple.comc04189e2017-01-18 05:17:17 +00001247 auto protectFrame = makeRef(m_frame);
inferno@chromium.org670ab752011-07-13 18:51:44 +00001248
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001249 URL url = request.resourceRequest().url();
antti@apple.comc633dca2008-11-14 21:34:55 +00001250
akling@apple.com7f50aae2013-08-22 16:01:31 +00001251 ASSERT(m_frame.document());
dbates@webkit.org174ac712017-06-30 21:35:23 +00001252 if (!request.requesterSecurityOrigin().canDisplay(url)) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00001253 reportLocalLoadFailed(&m_frame, url.stringCenterEllipsizedToLength());
darin@apple.com1cf3d562010-12-07 16:23:03 +00001254 return;
1255 }
1256
darin5a1e60e2007-04-17 19:58:16 +00001257 String argsReferrer = request.resourceRequest().httpReferrer();
jochen@chromium.org4761ef52011-11-21 10:29:55 +00001258 if (argsReferrer.isEmpty())
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001259 argsReferrer = outgoingReferrer();
antti@apple.comc633dca2008-11-14 21:34:55 +00001260
commit-queue@webkit.org8383b5f2020-03-02 11:36:00 +00001261 ReferrerPolicy referrerPolicy = request.referrerPolicy();
1262 if (referrerPolicy == ReferrerPolicy::EmptyString)
1263 referrerPolicy = m_frame.document()->referrerPolicy();
1264 String referrer = SecurityPolicy::generateReferrerHeader(referrerPolicy, url, argsReferrer);
beidson@apple.comee119d42015-04-28 19:38:13 +00001265
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001266 FrameLoadType loadType;
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00001267 if (request.resourceRequest().cachePolicy() == ResourceRequestCachePolicy::ReloadIgnoringCacheData)
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001268 loadType = FrameLoadType::Reload;
beidson@apple.comee119d42015-04-28 19:38:13 +00001269 else if (request.lockBackForwardList() == LockBackForwardList::Yes)
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001270 loadType = FrameLoadType::RedirectWithLockedBackForwardList;
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001271 else
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001272 loadType = FrameLoadType::Standard;
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001273
bfulgham@apple.com657c5c72018-05-24 05:23:00 +00001274 auto completionHandler = [this, protectedFrame = makeRef(m_frame), formState = makeWeakPtr(formState.get()), frameName = request.frameName()] {
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001275 // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
1276 // load if frame names have changed.
1277 Frame* sourceFrame = formState ? formState->sourceDocument().frame() : &m_frame;
1278 if (!sourceFrame)
1279 sourceFrame = &m_frame;
1280 Frame* targetFrame = sourceFrame->loader().findFrameForNavigation(frameName);
1281 if (targetFrame && targetFrame != sourceFrame) {
1282 if (Page* page = targetFrame->page())
1283 page->chrome().focus();
1284 }
1285 };
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001286
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001287 if (request.resourceRequest().httpMethod() == "POST")
bfulgham@apple.com657c5c72018-05-24 05:23:00 +00001288 loadPostRequest(WTFMove(request), referrer, loadType, event, WTFMove(formState), WTFMove(completionHandler));
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001289 else
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +00001290 loadURL(WTFMove(request), referrer, loadType, event, WTFMove(formState), WTFMove(adClickAttribution), WTFMove(completionHandler));
anderscade5715d2007-01-06 00:55:49 +00001291}
ddkilzer@apple.come6e7d422008-08-06 21:15:39 +00001292
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +00001293static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
mitz@apple.comc99c7152015-07-17 21:16:09 +00001294{
commit-queue@webkit.org635dbdc2017-11-23 19:36:08 +00001295 if (UserGestureIndicator::processingUserGesture())
mitz@apple.comc99c7152015-07-17 21:16:09 +00001296 return ShouldOpenExternalURLsPolicy::ShouldAllow;
beidson@apple.com7034ec72017-07-06 00:01:53 +00001297
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +00001298 if (initiatedByMainFrame == InitiatedByMainFrame::Yes)
beidson@apple.com7034ec72017-07-06 00:01:53 +00001299 return propagatedPolicy;
1300
1301 if (!currentFrame.isMainFrame())
1302 return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1303
mitz@apple.comc99c7152015-07-17 21:16:09 +00001304 return propagatedPolicy;
1305}
1306
beidson@apple.com7034ec72017-07-06 00:01:53 +00001307static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& currentFrame, const FrameLoadRequest& frameLoadRequest)
1308{
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +00001309 return shouldOpenExternalURLsPolicyToApply(currentFrame, frameLoadRequest.initiatedByMainFrame(), frameLoadRequest.shouldOpenExternalURLsPolicy());
beidson@apple.com7034ec72017-07-06 00:01:53 +00001310}
1311
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +00001312static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, InitiatedByMainFrame initiatedByMainFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
beidson@apple.com7034ec72017-07-06 00:01:53 +00001313{
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +00001314 documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, initiatedByMainFrame, propagatedPolicy));
beidson@apple.com7034ec72017-07-06 00:01:53 +00001315}
1316
1317static void applyShouldOpenExternalURLsPolicyToNewDocumentLoader(Frame& frame, DocumentLoader& documentLoader, const FrameLoadRequest& frameLoadRequest)
1318{
1319 documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(frame, frameLoadRequest));
1320}
1321
dbates@webkit.org872db612017-03-20 23:07:50 +00001322bool FrameLoader::isNavigationAllowed() const
1323{
beidson@apple.comb4571302019-08-08 15:54:37 +00001324 return m_pageDismissalEventBeingDispatched == PageDismissalType::None && !m_frame.script().willReplaceWithResultOfExecutingJavascriptURL() && NavigationDisabler::isNavigationAllowed(m_frame);
dbates@webkit.org872db612017-03-20 23:07:50 +00001325}
1326
pvollan@apple.com8f4bcd952018-02-01 04:18:38 +00001327bool FrameLoader::isStopLoadingAllowed() const
1328{
1329 return m_pageDismissalEventBeingDispatched == PageDismissalType::None;
1330}
1331
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +00001332void FrameLoader::loadURL(FrameLoadRequest&& frameLoadRequest, const String& referrer, FrameLoadType newLoadType, Event* event, RefPtr<FormState>&& formState, Optional<AdClickAttribution>&& adClickAttribution, CompletionHandler<void()>&& completionHandler)
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001333{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001334 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadURL: frame load started");
commit-queue@webkit.org8a13ad32020-03-16 08:11:26 +00001335 ASSERT(frameLoadRequest.resourceRequest().httpMethod() == "GET");
krollin@apple.come1810b62018-12-20 19:23:20 +00001336
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001337 CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
cdumez@apple.com8ace63b2018-06-29 22:56:29 +00001338 if (m_inStopAllLoaders || m_inClearProvisionalLoadForPolicyCheck)
commit-queue@webkit.orgcd5cda22011-02-15 15:55:21 +00001339 return;
1340
jpfau@apple.com18da22e2014-06-19 00:20:25 +00001341 Ref<Frame> protect(m_frame);
1342
cdumez@apple.com3ed26742018-10-09 23:21:18 +00001343 // Anchor target is ignored when the download attribute is set since it will download the hyperlink rather than follow it.
1344 String effectiveFrameName = frameLoadRequest.downloadAttribute().isNull() ? frameLoadRequest.frameName() : String();
andersca3513ce02007-05-17 08:38:44 +00001345 bool isFormSubmission = formState;
beidson@apple.combd66a782015-05-29 16:31:49 +00001346
commit-queue@webkit.orga6227742020-04-21 10:31:08 +00001347 // The search for a target frame is done earlier in the case of form submission.
1348 auto targetFrame = isFormSubmission ? nullptr : makeRefPtr(findFrameForNavigation(effectiveFrameName));
1349 if (targetFrame && targetFrame != &m_frame) {
1350 frameLoadRequest.setFrameName("_self");
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +00001351 targetFrame->loader().loadURL(WTFMove(frameLoadRequest), referrer, newLoadType, event, WTFMove(formState), WTFMove(adClickAttribution), completionHandlerCaller.release());
commit-queue@webkit.orga6227742020-04-21 10:31:08 +00001352 return;
1353 }
1354
beidson@apple.combd66a782015-05-29 16:31:49 +00001355 const URL& newURL = frameLoadRequest.resourceRequest().url();
weinig@apple.comc5002662007-12-12 07:26:19 +00001356 ResourceRequest request(newURL);
commit-queue@webkit.org34807862020-03-29 17:34:16 +00001357 if (!referrer.isEmpty())
anderscade5715d2007-01-06 00:55:49 +00001358 request.setHTTPReferrer(referrer);
commit-queue@webkit.org34807862020-03-29 17:34:16 +00001359
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00001360 addExtraFieldsToRequest(request, IsMainResource::Yes, newLoadType);
anderscade5715d2007-01-06 00:55:49 +00001361
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001362 ASSERT(newLoadType != FrameLoadType::Same);
anderscade5715d2007-01-06 00:55:49 +00001363
dbates@webkit.org872db612017-03-20 23:07:50 +00001364 if (!isNavigationAllowed())
eric@webkit.org6cae31a2009-09-26 02:35:15 +00001365 return;
1366
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00001367 NavigationAction action { frameLoadRequest.requester(), request, frameLoadRequest.initiatedByMainFrame(), newLoadType, isFormSubmission, event, frameLoadRequest.shouldOpenExternalURLsPolicy(), frameLoadRequest.downloadAttribute() };
commit-queue@webkit.orga6227742020-04-21 10:31:08 +00001368 action.setLockHistory(frameLoadRequest.lockHistory());
cdumez@apple.com05911a32018-10-23 17:54:34 +00001369 action.setLockBackForwardList(frameLoadRequest.lockBackForwardList());
commit-queue@webkit.orgf2719852020-11-11 04:55:57 +00001370 if (adClickAttribution && m_frame.isMainFrame())
1371 action.setAdClickAttribution(WTFMove(*adClickAttribution));
anderscade5715d2007-01-06 00:55:49 +00001372
commit-queue@webkit.orga6227742020-04-21 10:31:08 +00001373 NewFrameOpenerPolicy openerPolicy = frameLoadRequest.newFrameOpenerPolicy();
1374 AllowNavigationToInvalidURL allowNavigationToInvalidURL = frameLoadRequest.allowNavigationToInvalidURL();
cdumez@apple.com3ed26742018-10-09 23:21:18 +00001375 if (!targetFrame && !effectiveFrameName.isEmpty()) {
beidson@apple.com7034ec72017-07-06 00:01:53 +00001376 action = action.copyWithShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, frameLoadRequest));
commit-queue@webkit.org57af63c2020-04-29 10:23:01 +00001377 policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(request), WTFMove(formState), effectiveFrameName, [this, allowNavigationToInvalidURL, openerPolicy, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const String& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue) mutable {
bfulgham@apple.com657c5c72018-05-24 05:23:00 +00001378 continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001379 completionHandler();
andersca@apple.com096333f2013-11-07 21:37:36 +00001380 });
anderscade5715d2007-01-06 00:55:49 +00001381 return;
1382 }
1383
1384 RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1385
weinig@apple.comc5002662007-12-12 07:26:19 +00001386 bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
yael.aharon@nokia.com79f69052010-12-30 19:31:00 +00001387 const String& httpMethod = request.httpMethod();
anderscade5715d2007-01-06 00:55:49 +00001388
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001389 // Make sure to do scroll to fragment processing even if the URL is
anderscade5715d2007-01-06 00:55:49 +00001390 // exactly the same so pages with '#' links and DHTML side effects
1391 // work properly.
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001392 if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, newLoadType, newURL)) {
cdumez@apple.com91e03bd2018-09-17 17:15:07 +00001393 oldDocumentLoader->setTriggeringAction(WTFMove(action));
andersca@apple.com97ab6d92013-10-21 22:55:14 +00001394 oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001395 policyChecker().stopCheck();
1396 policyChecker().setLoadType(newLoadType);
rniwa@webkit.orgba12a012019-02-03 22:48:22 +00001397 RELEASE_ASSERT(!isBackForwardLoadType(newLoadType) || history().provisionalItem());
cdumez@apple.com2e665842019-02-01 22:52:58 +00001398 policyChecker().checkNavigationPolicy(WTFMove(request), ResourceResponse { } /* redirectResponse */, oldDocumentLoader.get(), WTFMove(formState), [this, protectedFrame = makeRef(m_frame)] (const ResourceRequest& request, WeakPtr<FormState>&&, NavigationPolicyDecision navigationPolicyDecision) {
1399 continueFragmentScrollAfterNavigationPolicy(request, navigationPolicyDecision == NavigationPolicyDecision::ContinueLoad);
cdumez@apple.com82211942018-04-17 18:13:49 +00001400 }, PolicyDecisionMode::Synchronous);
andersca@apple.com096333f2013-11-07 21:37:36 +00001401 return;
1402 }
1403
dino@apple.comb8e413d2018-05-08 20:12:24 +00001404 // Must grab this now, since this load may stop the previous load and clear this flag.
andersca@apple.com096333f2013-11-07 21:37:36 +00001405 bool isRedirect = m_quickRedirectComing;
dino@apple.com0bebb3a2018-05-22 23:56:01 +00001406#if USE(SYSTEM_PREVIEW)
1407 bool isSystemPreview = frameLoadRequest.isSystemPreview();
dino@apple.com0bebb3a2018-05-22 23:56:01 +00001408 if (isSystemPreview)
dino@apple.comddfbca82019-09-13 21:43:18 +00001409 request.setSystemPreviewInfo(frameLoadRequest.systemPreviewInfo());
dino@apple.com0bebb3a2018-05-22 23:56:01 +00001410#endif
commit-queue@webkit.orgbed33c62020-04-28 20:41:35 +00001411 loadWithNavigationAction(request, WTFMove(action), newLoadType, WTFMove(formState), allowNavigationToInvalidURL, [this, isRedirect, sameURL, newLoadType, protectedFrame = makeRef(m_frame), completionHandler = completionHandlerCaller.release()] () mutable {
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001412 if (isRedirect) {
1413 m_quickRedirectComing = false;
1414 if (m_provisionalDocumentLoader)
1415 m_provisionalDocumentLoader->setIsClientRedirect(true);
1416 else if (m_policyDocumentLoader)
1417 m_policyDocumentLoader->setIsClientRedirect(true);
1418 } else if (sameURL && !isReload(newLoadType)) {
1419 // Example of this case are sites that reload the same URL with a different cookie
1420 // driving the generated content, or a master frame with links that drive a target
1421 // frame, where the user has clicked on the same link repeatedly.
1422 m_loadType = FrameLoadType::Same;
1423 }
1424 completionHandler();
1425 });
anderscade5715d2007-01-06 00:55:49 +00001426}
1427
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001428SubstituteData FrameLoader::defaultSubstituteDataForURL(const URL& url)
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001429{
1430 if (!shouldTreatURLAsSrcdocDocument(url))
1431 return SubstituteData();
darin@apple.comf9da7a72017-06-04 18:19:16 +00001432 auto& srcdoc = m_frame.ownerElement()->attributeWithoutSynchronization(srcdocAttr);
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001433 ASSERT(!srcdoc.isNull());
darin@apple.comf9da7a72017-06-04 18:19:16 +00001434 CString encodedSrcdoc = srcdoc.string().utf8();
beidson@apple.comceb7cba2015-05-19 22:22:51 +00001435
utatane.tea@gmail.com84077632018-06-23 08:39:34 +00001436 ResourceResponse response(URL(), "text/html"_s, encodedSrcdoc.length(), "UTF-8"_s);
beidson@apple.comceb7cba2015-05-19 22:22:51 +00001437 return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001438}
1439
dbates@webkit.org7f3a9822017-06-22 19:45:10 +00001440void FrameLoader::load(FrameLoadRequest&& request)
anderscade5715d2007-01-06 00:55:49 +00001441{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001442 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "load (FrameLoadRequest): frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001443
cdumez@apple.com8ace63b2018-06-29 22:56:29 +00001444 if (m_inStopAllLoaders || m_inClearProvisionalLoadForPolicyCheck)
andersca8567b3d2007-03-21 05:46:49 +00001445 return;
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001446
1447 if (!request.frameName().isEmpty()) {
1448 Frame* frame = findFrameForNavigation(request.frameName());
1449 if (frame) {
1450 request.setShouldCheckNewWindowPolicy(false);
andersca@apple.comdf550b92013-08-15 22:17:17 +00001451 if (&frame->loader() != this) {
dbates@webkit.org7f3a9822017-06-22 19:45:10 +00001452 frame->loader().load(WTFMove(request));
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001453 return;
1454 }
1455 }
1456 }
1457
1458 if (request.shouldCheckNewWindowPolicy()) {
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00001459 NavigationAction action { request.requester(), request.resourceRequest(), InitiatedByMainFrame::Unknown, NavigationType::Other, request.shouldOpenExternalURLsPolicy() };
commit-queue@webkit.org57af63c2020-04-29 10:23:01 +00001460 policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(request.resourceRequest()), { }, request.frameName(), [this] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const String& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue) {
bfulgham@apple.com657c5c72018-05-24 05:23:00 +00001461 continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress);
andersca@apple.com096333f2013-11-07 21:37:36 +00001462 });
1463
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001464 return;
1465 }
1466
1467 if (!request.hasSubstituteData())
1468 request.setSubstituteData(defaultSubstituteDataForURL(request.resourceRequest().url()));
1469
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001470 Ref<DocumentLoader> loader = m_client->createDocumentLoader(request.resourceRequest(), request.substituteData());
jiewen_tan@apple.com32abaa62019-02-13 23:07:13 +00001471 loader->setAllowsWebArchiveForMainFrame(request.isRequestFromClientOrUserInput());
bfulgham@apple.com2eaf0ac2020-02-06 17:32:18 +00001472 loader->setAllowsDataURLsForMainFrame(request.isRequestFromClientOrUserInput());
dbates@webkit.org8c917f22018-04-24 07:36:59 +00001473 addSameSiteInfoToRequestIfNeeded(loader->request());
beidson@apple.com7034ec72017-07-06 00:01:53 +00001474 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, request);
beidson@apple.comd0558532015-05-28 04:52:25 +00001475
cdumez@apple.com4353b6e2018-10-26 05:06:24 +00001476 if (request.shouldTreatAsContinuingLoad()) {
cdumez@apple.com05911a32018-10-23 17:54:34 +00001477 loader->setClientRedirectSourceForHistory(request.clientRedirectSourceForHistory());
cdumez@apple.com4353b6e2018-10-26 05:06:24 +00001478 if (request.lockBackForwardList() == LockBackForwardList::Yes) {
1479 loader->setIsClientRedirect(true);
1480 m_loadType = FrameLoadType::RedirectWithLockedBackForwardList;
1481 }
cdumez@apple.com05911a32018-10-23 17:54:34 +00001482 }
1483
cdumez@apple.com3aedc032019-01-31 02:23:55 +00001484 SetForScope<LoadContinuingState> continuingLoadGuard(m_currentLoadContinuingState, request.shouldTreatAsContinuingLoad() ? LoadContinuingState::ContinuingWithRequest : LoadContinuingState::NotContinuing);
achristensen@apple.com10e4a7b2018-11-28 21:14:43 +00001485 load(loader.get());
anderscade5715d2007-01-06 00:55:49 +00001486}
1487
commit-queue@webkit.orgbed33c62020-04-28 20:41:35 +00001488void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, NavigationAction&& action, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
anderscade5715d2007-01-06 00:55:49 +00001489{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001490 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadWithNavigationAction: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001491
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001492 Ref<DocumentLoader> loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
dbates@webkit.org9692a072017-07-12 18:01:19 +00001493 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, action.initiatedByMainFrame(), action.shouldOpenExternalURLsPolicy());
beidson@apple.com87dc6312015-06-02 18:43:13 +00001494
commit-queue@webkit.org4a7ad282020-04-05 05:09:42 +00001495 if (action.lockHistory() == LockHistory::Yes && m_documentLoader)
commit-queue@webkit.org63040d02011-03-26 00:30:40 +00001496 loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
anderscade5715d2007-01-06 00:55:49 +00001497
cdumez@apple.com91e03bd2018-09-17 17:15:07 +00001498 loader->setTriggeringAction(WTFMove(action));
anderscade5715d2007-01-06 00:55:49 +00001499 if (m_documentLoader)
1500 loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1501
commit-queue@webkit.org372c2642020-04-03 16:53:48 +00001502 loadWithDocumentLoader(loader.ptr(), type, WTFMove(formState), allowNavigationToInvalidURL, WTFMove(completionHandler));
anderscade5715d2007-01-06 00:55:49 +00001503}
1504
achristensen@apple.com10e4a7b2018-11-28 21:14:43 +00001505void FrameLoader::load(DocumentLoader& newDocumentLoader)
anderscade5715d2007-01-06 00:55:49 +00001506{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001507 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "load (DocumentLoader): frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001508
achristensen@apple.com22b9ddf2018-08-17 23:24:37 +00001509 ResourceRequest& r = newDocumentLoader.request();
commit-queue@webkit.org53c0a6b2020-04-02 07:43:14 +00001510 // FIXME: Using m_loadType seems wrong here.
1511 // If we are only preparing to load the main resource, that is previous load's load type!
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00001512 addExtraFieldsToRequest(r, IsMainResource::Yes, m_loadType);
anderscade5715d2007-01-06 00:55:49 +00001513 FrameLoadType type;
1514
achristensen@apple.com22b9ddf2018-08-17 23:24:37 +00001515 if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.originalRequest().url())) {
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00001516 r.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001517 type = FrameLoadType::Same;
achristensen@apple.com22b9ddf2018-08-17 23:24:37 +00001518 } else if (shouldTreatURLAsSameAsCurrent(newDocumentLoader.unreachableURL()) && isReload(m_loadType))
commit-queue@webkit.orgfb4593b2018-04-18 17:50:15 +00001519 type = m_loadType;
cdumez@apple.com3aedc032019-01-31 02:23:55 +00001520 else if (m_loadType == FrameLoadType::RedirectWithLockedBackForwardList && ((!newDocumentLoader.unreachableURL().isEmpty() && newDocumentLoader.substituteData().isValid()) || shouldTreatCurrentLoadAsContinuingLoad()))
aestes@apple.com176a9aa2016-07-08 20:14:34 +00001521 type = FrameLoadType::RedirectWithLockedBackForwardList;
jpfau@apple.com6e5a6052012-07-27 00:52:32 +00001522 else
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001523 type = FrameLoadType::Standard;
anderscade5715d2007-01-06 00:55:49 +00001524
1525 if (m_documentLoader)
achristensen@apple.com22b9ddf2018-08-17 23:24:37 +00001526 newDocumentLoader.setOverrideEncoding(m_documentLoader->overrideEncoding());
anderscade5715d2007-01-06 00:55:49 +00001527
1528 // When we loading alternate content for an unreachable URL that we're
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001529 // visiting in the history list, we treat it as a reload so the history list
anderscade5715d2007-01-06 00:55:49 +00001530 // is appropriately maintained.
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001531 //
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001532 // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadType::Reload" ...
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001533 // shouldn't a more explicit type of reload be defined, that means roughly
1534 // "load without affecting history" ?
mjs2d326f52007-01-29 12:50:49 +00001535 if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
achristensen@apple.com22b9ddf2018-08-17 23:24:37 +00001536 // shouldReloadToHandleUnreachableURL returns true only when the original load type is back-forward.
commit-queue@webkit.org072ac242011-04-04 17:05:55 +00001537 // In this case we should save the document state now. Otherwise the state can be lost because load type is
1538 // changed and updateForBackForwardNavigation() will not be called when loading is committed.
akling@apple.com672cb852013-08-22 20:27:27 +00001539 history().saveDocumentAndScrollState();
commit-queue@webkit.org072ac242011-04-04 17:05:55 +00001540
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001541 ASSERT(type == FrameLoadType::Standard);
1542 type = FrameLoadType::Reload;
anderscade5715d2007-01-06 00:55:49 +00001543 }
1544
commit-queue@webkit.org372c2642020-04-03 16:53:48 +00001545 loadWithDocumentLoader(&newDocumentLoader, type, nullptr, AllowNavigationToInvalidURL::Yes);
anderscade5715d2007-01-06 00:55:49 +00001546}
1547
commit-queue@webkit.org372c2642020-04-03 16:53:48 +00001548void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, RefPtr<FormState>&& formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL, CompletionHandler<void()>&& completionHandler)
anderscade5715d2007-01-06 00:55:49 +00001549{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001550 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadWithDocumentLoader: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001551
inferno@chromium.org6e8e3472010-10-26 13:29:04 +00001552 // Retain because dispatchBeforeLoadEvent may release the last reference to it.
akling@apple.comf8515982013-09-02 18:50:01 +00001553 Ref<Frame> protect(m_frame);
inferno@chromium.org6e8e3472010-10-26 13:29:04 +00001554
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001555 CompletionHandlerCallingScope completionHandlerCaller(WTFMove(completionHandler));
1556
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001557 ASSERT(m_client->hasWebView());
anderscade5715d2007-01-06 00:55:49 +00001558
1559 // Unfortunately the view must be non-nil, this is ultimately due
1560 // to parser requiring a FrameView. We should fix this dependency.
1561
akling@apple.com7f50aae2013-08-22 16:01:31 +00001562 ASSERT(m_frame.view());
anderscade5715d2007-01-06 00:55:49 +00001563
dbates@webkit.org872db612017-03-20 23:07:50 +00001564 if (!isNavigationAllowed())
abarth@webkit.org89fa3502009-09-21 02:30:12 +00001565 return;
1566
akling@apple.com7f50aae2013-08-22 16:01:31 +00001567 if (m_frame.document())
1568 m_previousURL = m_frame.document()->url();
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001569
cdumez@apple.comeb4832c2017-02-08 15:39:38 +00001570 const URL& newURL = loader->request().url();
1571
jiewen_tan@apple.com1306fce2018-10-24 18:49:03 +00001572 // Only the first iframe navigation or the first iframe navigation after about:blank should be reported.
1573 // https://www.w3.org/TR/resource-timing-2/#resources-included-in-the-performanceresourcetiming-interface
youenn@apple.com55cf9a22020-03-23 19:46:57 +00001574 if (m_shouldReportResourceTimingToParentFrame && !m_previousURL.isNull() && m_previousURL != aboutBlankURL())
jiewen_tan@apple.com1306fce2018-10-24 18:49:03 +00001575 m_shouldReportResourceTimingToParentFrame = false;
1576
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001577 // Log main frame navigation types.
akling@apple.come6549f42016-12-01 16:15:27 +00001578 if (m_frame.isMainFrame()) {
cdumez@apple.comc518f7e2018-04-03 18:01:41 +00001579 if (auto* page = m_frame.page()) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00001580 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadWithDocumentLoader: main frame load started");
cdumez@apple.com563f1dc2017-04-29 03:55:35 +00001581 page->mainFrameLoadStarted(newURL, type);
cdumez@apple.comc518f7e2018-04-03 18:01:41 +00001582 page->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadStarted);
1583 }
akling@apple.come6549f42016-12-01 16:15:27 +00001584 }
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001585
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001586 policyChecker().setLoadType(type);
rniwa@webkit.orgba12a012019-02-03 22:48:22 +00001587 RELEASE_ASSERT(!isBackForwardLoadType(type) || history().provisionalItem());
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00001588 bool isFormSubmission = formState;
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001589
yael.aharon@nokia.com79f69052010-12-30 19:31:00 +00001590 const String& httpMethod = loader->request().httpMethod();
anderscade5715d2007-01-06 00:55:49 +00001591
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001592 if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) {
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00001593 RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00001594 NavigationAction action { *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission };
anderscade5715d2007-01-06 00:55:49 +00001595
cdumez@apple.com91e03bd2018-09-17 17:15:07 +00001596 oldDocumentLoader->setTriggeringAction(WTFMove(action));
andersca@apple.com97ab6d92013-10-21 22:55:14 +00001597 oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001598 policyChecker().stopCheck();
rniwa@webkit.orgba12a012019-02-03 22:48:22 +00001599 RELEASE_ASSERT(!isBackForwardLoadType(policyChecker().loadType()) || history().provisionalItem());
cdumez@apple.com2e665842019-02-01 22:52:58 +00001600 policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { } /* redirectResponse */, oldDocumentLoader.get(), WTFMove(formState), [this, protectedFrame = makeRef(m_frame)] (const ResourceRequest& request, WeakPtr<FormState>&&, NavigationPolicyDecision navigationPolicyDecision) {
1601 continueFragmentScrollAfterNavigationPolicy(request, navigationPolicyDecision == NavigationPolicyDecision::ContinueLoad);
cdumez@apple.com82211942018-04-17 18:13:49 +00001602 }, PolicyDecisionMode::Synchronous);
andersca@apple.com096333f2013-11-07 21:37:36 +00001603 return;
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00001604 }
andersca@apple.com096333f2013-11-07 21:37:36 +00001605
1606 if (Frame* parent = m_frame.tree().parent())
1607 loader->setOverrideEncoding(parent->loader().documentLoader()->overrideEncoding());
1608
1609 policyChecker().stopCheck();
1610 setPolicyDocumentLoader(loader);
1611 if (loader->triggeringAction().isEmpty())
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00001612 loader->setTriggeringAction({ *m_frame.document(), loader->request(), InitiatedByMainFrame::Unknown, policyChecker().loadType(), isFormSubmission });
andersca@apple.com096333f2013-11-07 21:37:36 +00001613
1614 if (Element* ownerElement = m_frame.ownerElement()) {
1615 // We skip dispatching the beforeload event if we've already
1616 // committed a real document load because the event would leak
1617 // subsequent activity by the frame which the parent frame isn't
1618 // supposed to learn. For example, if the child frame navigated to
1619 // a new URL, the parent frame shouldn't learn the URL.
1620 if (!m_stateMachine.committedFirstRealDocumentLoad()
1621 && !ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) {
cdumez@apple.com2e665842019-02-01 22:52:58 +00001622 continueLoadAfterNavigationPolicy(loader->request(), formState.get(), NavigationPolicyDecision::IgnoreLoad, allowNavigationToInvalidURL);
andersca@apple.com096333f2013-11-07 21:37:36 +00001623 return;
1624 }
1625 }
1626
achristensen@apple.com6fddc912018-10-18 21:16:52 +00001627 m_frame.navigationScheduler().cancel(NewLoadInProgress::Yes);
cdumez@apple.com22fa18d2018-02-28 23:58:22 +00001628
cdumez@apple.com3aedc032019-01-31 02:23:55 +00001629 if (shouldTreatCurrentLoadAsContinuingLoad()) {
cdumez@apple.com2e665842019-02-01 22:52:58 +00001630 continueLoadAfterNavigationPolicy(loader->request(), formState.get(), NavigationPolicyDecision::ContinueLoad, allowNavigationToInvalidURL);
beidson@apple.com1c9022b2018-03-21 00:05:58 +00001631 return;
1632 }
1633
rniwa@webkit.orgba12a012019-02-03 22:48:22 +00001634 RELEASE_ASSERT(!isBackForwardLoadType(policyChecker().loadType()) || history().provisionalItem());
cdumez@apple.com2e665842019-02-01 22:52:58 +00001635 policyChecker().checkNavigationPolicy(ResourceRequest(loader->request()), ResourceResponse { } /* redirectResponse */, loader, WTFMove(formState), [this, protectedFrame = makeRef(m_frame), allowNavigationToInvalidURL, completionHandler = completionHandlerCaller.release()] (const ResourceRequest& request, WeakPtr<FormState>&& formState, NavigationPolicyDecision navigationPolicyDecision) mutable {
1636 continueLoadAfterNavigationPolicy(request, formState.get(), navigationPolicyDecision, allowNavigationToInvalidURL);
cdumez@apple.comb76757c2018-03-06 22:01:27 +00001637 completionHandler();
achristensen@apple.com10e4a7b2018-11-28 21:14:43 +00001638 }, PolicyDecisionMode::Asynchronous);
anderscade5715d2007-01-06 00:55:49 +00001639}
1640
cdumez@apple.com2e68bb42018-03-19 22:30:57 +00001641void FrameLoader::clearProvisionalLoadForPolicyCheck()
1642{
cdumez@apple.com8ace63b2018-06-29 22:56:29 +00001643 if (!m_policyDocumentLoader || !m_provisionalDocumentLoader || m_inClearProvisionalLoadForPolicyCheck)
cdumez@apple.com2e68bb42018-03-19 22:30:57 +00001644 return;
1645
cdumez@apple.com8ace63b2018-06-29 22:56:29 +00001646 SetForScope<bool> change(m_inClearProvisionalLoadForPolicyCheck, true);
cdumez@apple.com2e68bb42018-03-19 22:30:57 +00001647 m_provisionalDocumentLoader->stopLoading();
krollin@apple.combdeaed72020-01-08 01:31:20 +00001648 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "clearProvisionalLoadForPolicyCheck: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
cdumez@apple.com2e68bb42018-03-19 22:30:57 +00001649 setProvisionalDocumentLoader(nullptr);
1650}
1651
achristensen@apple.com2ace43d2020-11-05 16:54:48 +00001652bool FrameLoader::hasOpenedFrames() const
1653{
1654 return !m_openedFrames.computesEmpty();
1655}
1656
aroben@apple.com92cfa902008-04-16 19:19:00 +00001657void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
kmccullo23d362f2007-04-06 01:05:58 +00001658{
1659 ASSERT(!url.isEmpty());
aroben@apple.com92cfa902008-04-16 19:19:00 +00001660 if (!frame)
1661 return;
1662
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00001663 frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to load local resource: " + url);
kmccullo23d362f2007-04-06 01:05:58 +00001664}
1665
anderscade5715d2007-01-06 00:55:49 +00001666const ResourceRequest& FrameLoader::initialRequest() const
1667{
andersca@apple.com48ffa332008-03-13 19:08:06 +00001668 return activeDocumentLoader()->originalRequest();
anderscade5715d2007-01-06 00:55:49 +00001669}
1670
drousso@apple.com21748ed2018-10-08 18:25:52 +00001671bool FrameLoader::willLoadMediaElementURL(URL& url, Node& initiatorNode)
weinig@apple.com68935252009-10-07 02:48:12 +00001672{
ap@apple.com1e8475922018-10-18 21:38:50 +00001673#if PLATFORM(IOS_FAMILY)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001674 // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource
1675 // doesn't let them tell when a load request is coming from a media element. See <rdar://problem/8266916> for more details.
cdumez@apple.com0b0e88f2016-03-06 03:28:54 +00001676 if (IOSApplication::isMobileStore())
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001677 return m_client->shouldLoadMediaElementURL(url);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001678#endif
1679
weinig@apple.com68935252009-10-07 02:48:12 +00001680 ResourceRequest request(url);
drousso@apple.com21748ed2018-10-08 18:25:52 +00001681 request.setInspectorInitiatorNodeIdentifier(InspectorInstrumentation::identifierForNode(initiatorNode));
weinig@apple.com68935252009-10-07 02:48:12 +00001682
1683 unsigned long identifier;
1684 ResourceError error;
1685 requestFromDelegate(request, identifier, error);
antti@apple.com021dc012014-09-04 20:00:11 +00001686 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, ResourceResponse(url, String(), -1, String()), 0, -1, -1, error);
weinig@apple.com68935252009-10-07 02:48:12 +00001687
1688 url = request.url();
1689
1690 return error.isNull();
1691}
1692
achristensen@apple.com22b9ddf2018-08-17 23:24:37 +00001693bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader& docLoader)
anderscade5715d2007-01-06 00:55:49 +00001694{
achristensen@apple.com22b9ddf2018-08-17 23:24:37 +00001695 URL unreachableURL = docLoader.unreachableURL();
anderscade5715d2007-01-06 00:55:49 +00001696
1697 if (unreachableURL.isEmpty())
1698 return false;
1699
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001700 if (!isBackForwardLoadType(policyChecker().loadType()))
anderscade5715d2007-01-06 00:55:49 +00001701 return false;
1702
1703 // We only treat unreachableURLs specially during the delegate callbacks
1704 // for provisional load errors and navigation policy decisions. The former
1705 // case handles well-formed URLs that can't be loaded, and the latter
1706 // case handles malformed URLs and unknown schemes. Loading alternate content
1707 // at other times behaves like a standard load.
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001708 if (policyChecker().delegateIsDecidingNavigationPolicy() || policyChecker().delegateIsHandlingUnimplementablePolicy())
mitz@apple.com6699e272015-05-01 23:47:03 +00001709 return m_policyDocumentLoader && unreachableURL == m_policyDocumentLoader->request().url();
anderscade5715d2007-01-06 00:55:49 +00001710
mitz@apple.com6699e272015-05-01 23:47:03 +00001711 return unreachableURL == m_provisionalLoadErrorBeingHandledURL;
anderscade5715d2007-01-06 00:55:49 +00001712}
1713
ggaren@apple.com3eaa7c02009-01-29 07:38:54 +00001714void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
anderscade5715d2007-01-06 00:55:49 +00001715{
1716 if (!m_documentLoader)
1717 return;
1718
krollin@apple.combdeaed72020-01-08 01:31:20 +00001719 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "reloadWithOverrideEncoding: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001720
anderscade5715d2007-01-06 00:55:49 +00001721 ResourceRequest request = m_documentLoader->request();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001722 URL unreachableURL = m_documentLoader->unreachableURL();
anderscade5715d2007-01-06 00:55:49 +00001723 if (!unreachableURL.isEmpty())
1724 request.setURL(unreachableURL);
1725
ap@apple.com8d5f01b2013-01-07 18:40:55 +00001726 // FIXME: If the resource is a result of form submission and is not cached, the form will be silently resubmitted.
1727 // We should ask the user for confirmation in this case.
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00001728 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
anderscade5715d2007-01-06 00:55:49 +00001729
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001730 Ref<DocumentLoader> loader = m_client->createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +00001731 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
beidson@apple.com87dc6312015-06-02 18:43:13 +00001732
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001733 setPolicyDocumentLoader(loader.ptr());
anderscade5715d2007-01-06 00:55:49 +00001734
1735 loader->setOverrideEncoding(encoding);
1736
commit-queue@webkit.org372c2642020-04-03 16:53:48 +00001737 loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, { }, AllowNavigationToInvalidURL::Yes);
anderscade5715d2007-01-06 00:55:49 +00001738}
1739
antti@apple.com5d0c5402017-03-17 19:52:49 +00001740void FrameLoader::reload(OptionSet<ReloadOption> options)
anderscade5715d2007-01-06 00:55:49 +00001741{
1742 if (!m_documentLoader)
1743 return;
1744
anderscade5715d2007-01-06 00:55:49 +00001745 // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1746 // Reloading in this case will lose the current contents (see 4151001).
darin@chromium.org48246852008-11-04 19:40:56 +00001747 if (m_documentLoader->request().url().isEmpty())
anderscade5715d2007-01-06 00:55:49 +00001748 return;
1749
krollin@apple.combdeaed72020-01-08 01:31:20 +00001750 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "reload: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00001751
anderscade5715d2007-01-06 00:55:49 +00001752 // Replace error-page URL with the URL we were trying to reach.
commit-queue@webkit.org2090e272012-06-28 16:05:43 +00001753 ResourceRequest initialRequest = m_documentLoader->request();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001754 URL unreachableURL = m_documentLoader->unreachableURL();
anderscade5715d2007-01-06 00:55:49 +00001755 if (!unreachableURL.isEmpty())
darin@chromium.org48246852008-11-04 19:40:56 +00001756 initialRequest.setURL(unreachableURL);
commit-queue@webkit.org2090e272012-06-28 16:05:43 +00001757
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001758 // Create a new document loader for the reload, this will become m_documentLoader eventually,
1759 // but first it has to be the "policy" document loader, and then the "provisional" document loader.
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001760 Ref<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, defaultSubstituteDataForURL(initialRequest.url()));
jiewen_tan@apple.com32abaa62019-02-13 23:07:13 +00001761 loader->setAllowsWebArchiveForMainFrame(m_documentLoader->allowsWebArchiveForMainFrame());
bfulgham@apple.com2eaf0ac2020-02-06 17:32:18 +00001762 loader->setAllowsDataURLsForMainFrame(m_documentLoader->allowsDataURLsForMainFrame());
dbates@webkit.orgdc3a7cf2017-07-12 17:12:07 +00001763 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(m_frame, loader, InitiatedByMainFrame::Unknown, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
anderscade5715d2007-01-06 00:55:49 +00001764
antti@apple.com5d0c5402017-03-17 19:52:49 +00001765 loader->setUserContentExtensionsEnabled(!options.contains(ReloadOption::DisableContentBlockers));
achristensen@apple.comd40e0ba2015-10-14 20:03:14 +00001766
anderscade5715d2007-01-06 00:55:49 +00001767 ResourceRequest& request = loader->request();
1768
commit-queue@webkit.org4833ac52018-02-26 17:38:14 +00001769 // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00001770 request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
anderscade5715d2007-01-06 00:55:49 +00001771
dbates@webkit.org8c917f22018-04-24 07:36:59 +00001772 addSameSiteInfoToRequestIfNeeded(request);
1773
anderscade5715d2007-01-06 00:55:49 +00001774 // If we're about to re-post, set up action so the application can warn the user.
1775 if (request.httpMethod() == "POST")
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00001776 loader->setTriggeringAction({ *m_frame.document(), request, InitiatedByMainFrame::Unknown, NavigationType::FormResubmitted });
anderscade5715d2007-01-06 00:55:49 +00001777
1778 loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
antti@apple.com5d0c5402017-03-17 19:52:49 +00001779
1780 auto frameLoadTypeForReloadOptions = [] (auto options) {
antti@apple.comeb7081d2018-05-09 07:05:46 +00001781 if (options & ReloadOption::FromOrigin)
antti@apple.com5d0c5402017-03-17 19:52:49 +00001782 return FrameLoadType::ReloadFromOrigin;
antti@apple.comeb7081d2018-05-09 07:05:46 +00001783 if (options & ReloadOption::ExpiredOnly)
antti@apple.com5d0c5402017-03-17 19:52:49 +00001784 return FrameLoadType::ReloadExpiredOnly;
1785 return FrameLoadType::Reload;
1786 };
anderscade5715d2007-01-06 00:55:49 +00001787
commit-queue@webkit.org372c2642020-04-03 16:53:48 +00001788 loadWithDocumentLoader(loader.ptr(), frameLoadTypeForReloadOptions(options), { }, AllowNavigationToInvalidURL::Yes);
anderscade5715d2007-01-06 00:55:49 +00001789}
1790
ajuma@chromium.orgedd75742019-09-11 14:52:18 +00001791void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy, StopLoadingPolicy stopLoadingPolicy)
darinc370e7e2006-11-08 05:52:27 +00001792{
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00001793 if (m_frame.document() && m_frame.document()->backForwardCacheState() == Document::InBackForwardCache)
cdumez@apple.coma0010ff2018-12-13 23:17:44 +00001794 return;
1795
ajuma@chromium.orgedd75742019-09-11 14:52:18 +00001796 if (stopLoadingPolicy == StopLoadingPolicy::PreventDuringUnloadEvents && !isStopLoadingAllowed())
weinig@apple.comf239bbf2009-04-09 18:30:32 +00001797 return;
1798
darinc370e7e2006-11-08 05:52:27 +00001799 // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1800 if (m_inStopAllLoaders)
1801 return;
pvollan@apple.com8f4bcd952018-02-01 04:18:38 +00001802
1803 // This method might dispatch events.
1804 RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(ScriptDisallowedScope::InMainThread::isScriptAllowed());
1805
inferno@chromium.orgbc05aa52012-08-06 16:30:40 +00001806 // Calling stopLoading() on the provisional document loader can blow away
1807 // the frame from underneath.
akling@apple.comf8515982013-09-02 18:50:01 +00001808 Ref<Frame> protect(m_frame);
darinc370e7e2006-11-08 05:52:27 +00001809
1810 m_inStopAllLoaders = true;
1811
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001812 policyChecker().stopCheck();
darinc370e7e2006-11-08 05:52:27 +00001813
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00001814 // If no new load is in progress, we should clear the provisional item from history
1815 // before we call stopLoading.
1816 if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00001817 history().setProvisionalItem(nullptr);
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00001818
darin@apple.comfed4d162013-08-25 02:28:06 +00001819 for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
andersca@apple.comdf550b92013-08-15 22:17:17 +00001820 child->loader().stopAllLoaders(clearProvisionalItemPolicy);
darin7208e932007-02-13 17:52:53 +00001821 if (m_provisionalDocumentLoader)
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +00001822 m_provisionalDocumentLoader->stopLoading();
beidson@apple.com46421212008-08-25 21:48:56 +00001823 if (m_documentLoader)
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +00001824 m_documentLoader->stopLoading();
commit-queue@webkit.org424bc412020-02-24 15:50:39 +00001825 if (m_frame.page() && !m_frame.page()->chrome().client().isSVGImageChromeClient())
1826 platformStrategies()->loaderStrategy()->browsingContextRemoved(frame());
beidson@apple.com46421212008-08-25 21:48:56 +00001827
krollin@apple.combdeaed72020-01-08 01:31:20 +00001828 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "stopAllLoaders: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00001829 setProvisionalDocumentLoader(nullptr);
darin7208e932007-02-13 17:52:53 +00001830
darinc370e7e2006-11-08 05:52:27 +00001831 m_inStopAllLoaders = false;
1832}
1833
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00001834void FrameLoader::stopForBackForwardCache()
cdumez@apple.come16aaf02019-10-03 22:16:46 +00001835{
cdumez@apple.come16aaf02019-10-03 22:16:46 +00001836 // Stop provisional loads in subframes (The one in the main frame is about to be committed).
1837 if (!m_frame.isMainFrame()) {
1838 if (m_provisionalDocumentLoader)
1839 m_provisionalDocumentLoader->stopLoading();
krollin@apple.combdeaed72020-01-08 01:31:20 +00001840 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "stopForBackForwardCache: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
cdumez@apple.come16aaf02019-10-03 22:16:46 +00001841 setProvisionalDocumentLoader(nullptr);
1842 }
1843
1844 // Stop current loads.
1845 if (m_documentLoader)
1846 m_documentLoader->stopLoading();
1847
1848 for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00001849 child->loader().stopForBackForwardCache();
cdumez@apple.com6cbf70a2019-10-11 20:26:15 +00001850
cdumez@apple.com7e7b8792019-10-11 23:29:02 +00001851 // We cancel pending navigations & policy checks *after* cancelling loads because cancelling loads might end up
1852 // running script, which could schedule new navigations.
cdumez@apple.com6cbf70a2019-10-11 20:26:15 +00001853 policyChecker().stopCheck();
1854 m_frame.navigationScheduler().cancel();
cdumez@apple.come16aaf02019-10-03 22:16:46 +00001855}
1856
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +00001857void FrameLoader::stopAllLoadersAndCheckCompleteness()
1858{
1859 stopAllLoaders();
1860
1861 if (!m_checkTimer.isActive())
1862 return;
1863
1864 m_checkTimer.stop();
1865 m_checkingLoadCompleteForDetachment = true;
1866 checkCompletenessNow();
1867 m_checkingLoadCompleteForDetachment = false;
1868}
1869
beidson398923b2007-07-31 20:29:02 +00001870void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
mjs8d620d52007-05-10 12:31:42 +00001871{
bfulgham@apple.com98845d92016-05-17 01:09:27 +00001872 // Calling stopAllLoaders can cause the frame to be deallocated, including the frame loader.
1873 Ref<Frame> protectedFrame(m_frame);
1874
mjs8d620d52007-05-10 12:31:42 +00001875 stopAllLoaders();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001876
ap@apple.com1e8475922018-10-18 21:38:50 +00001877#if PLATFORM(IOS_FAMILY)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001878 // Lay out immediately when stopping to immediately clear the old page if we just committed this one
1879 // but haven't laid out/painted yet.
1880 // FIXME: Is this behavior specific to iOS? Or should we expose a setting to toggle this behavior?
1881 if (m_frame.view() && !m_frame.view()->didFirstLayout())
zalan@apple.com6116e6d2017-10-28 15:24:58 +00001882 m_frame.view()->layoutContext().layout();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001883#endif
1884
beidson398923b2007-07-31 20:29:02 +00001885 if (deferCheckLoadComplete)
1886 scheduleCheckLoadComplete();
akling@apple.com7f50aae2013-08-22 16:01:31 +00001887 else if (m_frame.page())
mjs8d620d52007-05-10 12:31:42 +00001888 checkLoadComplete();
1889}
1890
darinc370e7e2006-11-08 05:52:27 +00001891DocumentLoader* FrameLoader::activeDocumentLoader() const
1892{
1893 if (m_state == FrameStateProvisional)
1894 return m_provisionalDocumentLoader.get();
1895 return m_documentLoader.get();
1896}
1897
darinc370e7e2006-11-08 05:52:27 +00001898bool FrameLoader::isLoading() const
1899{
darin8207db42007-02-20 18:18:39 +00001900 DocumentLoader* docLoader = activeDocumentLoader();
1901 if (!docLoader)
1902 return false;
japhet@chromium.org4bcb80b2012-03-26 20:34:00 +00001903 return docLoader->isLoading();
darinc370e7e2006-11-08 05:52:27 +00001904}
1905
mjs7545bb52007-05-15 08:24:53 +00001906bool FrameLoader::frameHasLoaded() const
1907{
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00001908 return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument());
mjs7545bb52007-05-15 08:24:53 +00001909}
1910
darinc370e7e2006-11-08 05:52:27 +00001911void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1912{
1913 if (!loader && !m_documentLoader)
1914 return;
cdumez@apple.coma0010ff2018-12-13 23:17:44 +00001915
1916 if (loader == m_documentLoader)
1917 return;
darinc370e7e2006-11-08 05:52:27 +00001918
1919 ASSERT(loader != m_documentLoader);
1920 ASSERT(!loader || loader->frameLoader() == this);
1921
youenn@apple.comee96d0f2020-03-18 13:59:23 +00001922 m_client->prepareForDataSourceReplacement();
darinc3d26052007-03-22 18:17:12 +00001923 detachChildren();
japhet@chromium.orga9a58bb2012-09-01 01:09:02 +00001924
1925 // detachChildren() can trigger this frame's unload event, and therefore
1926 // script can run and do just about anything. For example, an unload event that calls
1927 // document.write("") on its parent frame can lead to a recursive detachChildren()
1928 // invocation for this frame. In that case, we can end up at this point with a
1929 // loader that hasn't been deleted but has been detached from its frame. Such a
1930 // DocumentLoader has been sufficiently detached that we'll end up in an inconsistent
1931 // state if we try to use it.
1932 if (loader && !loader->frame())
1933 return;
1934
darinc370e7e2006-11-08 05:52:27 +00001935 if (m_documentLoader)
1936 m_documentLoader->detachFromFrame();
1937
1938 m_documentLoader = loader;
1939}
1940
darinc370e7e2006-11-08 05:52:27 +00001941void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1942{
1943 if (m_policyDocumentLoader == loader)
1944 return;
1945
darinc370e7e2006-11-08 05:52:27 +00001946 if (loader)
beidson@apple.com10a537f2015-07-09 22:30:42 +00001947 loader->attachToFrame(m_frame);
darinc370e7e2006-11-08 05:52:27 +00001948 if (m_policyDocumentLoader
1949 && m_policyDocumentLoader != m_provisionalDocumentLoader
1950 && m_policyDocumentLoader != m_documentLoader)
1951 m_policyDocumentLoader->detachFromFrame();
1952
1953 m_policyDocumentLoader = loader;
1954}
eric@webkit.org14774f42008-04-21 17:50:37 +00001955
darinc370e7e2006-11-08 05:52:27 +00001956void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1957{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001958 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "setProvisionalDocumentLoader: Setting provisional document loader (m_provisionalDocumentLoader=%p)", loader);
1959
darinc370e7e2006-11-08 05:52:27 +00001960 ASSERT(!loader || !m_provisionalDocumentLoader);
1961 ASSERT(!loader || loader->frameLoader() == this);
1962
1963 if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1964 m_provisionalDocumentLoader->detachFromFrame();
1965
1966 m_provisionalDocumentLoader = loader;
1967}
1968
darinc370e7e2006-11-08 05:52:27 +00001969void FrameLoader::setState(FrameState newState)
akling@apple.come6549f42016-12-01 16:15:27 +00001970{
1971 FrameState oldState = m_state;
darinc370e7e2006-11-08 05:52:27 +00001972 m_state = newState;
1973
1974 if (newState == FrameStateProvisional)
1975 provisionalLoadStarted();
1976 else if (newState == FrameStateComplete) {
1977 frameLoadCompleted();
darinc370e7e2006-11-08 05:52:27 +00001978 if (m_documentLoader)
1979 m_documentLoader->stopRecordingResponses();
krollin@apple.come1810b62018-12-20 19:23:20 +00001980 if (m_frame.isMainFrame() && oldState != newState) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00001981 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "setState: main frame load completed");
cdumez@apple.comc518f7e2018-04-03 18:01:41 +00001982 m_frame.page()->performanceLogging().didReachPointOfInterest(PerformanceLogging::MainFrameLoadCompleted);
krollin@apple.come1810b62018-12-20 19:23:20 +00001983 }
darinc370e7e2006-11-08 05:52:27 +00001984 }
1985}
1986
1987void FrameLoader::clearProvisionalLoad()
1988{
krollin@apple.combdeaed72020-01-08 01:31:20 +00001989 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "clearProvisionalLoad: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00001990 setProvisionalDocumentLoader(nullptr);
japhet@chromium.org7879dd72012-08-30 02:58:37 +00001991 m_progressTracker->progressCompleted();
darinc370e7e2006-11-08 05:52:27 +00001992 setState(FrameStateComplete);
1993}
1994
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00001995void FrameLoader::commitProvisionalLoad()
beidson50c3bd82007-01-03 03:11:18 +00001996{
beidson50c3bd82007-01-03 03:11:18 +00001997 RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
akling@apple.comf8515982013-09-02 18:50:01 +00001998 Ref<Frame> protect(m_frame);
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00001999
andersca@apple.come776c2f2014-01-18 01:47:19 +00002000 std::unique_ptr<CachedPage> cachedPage;
cdumez@apple.com67e10f72015-01-29 18:38:51 +00002001 if (m_loadingFromCachedPage && history().provisionalItem())
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00002002 cachedPage = BackForwardCache::singleton().take(*history().provisionalItem(), m_frame.page());
akling@apple.com9663f4b2013-09-05 21:25:32 +00002003
cdumez@apple.com524b8aa2019-10-15 05:28:55 +00002004 LOG(BackForwardCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s' with cached page %p", m_frame.tree().uniqueName().string().utf8().data(),
akling@apple.com7f50aae2013-08-22 16:01:31 +00002005 m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
beidson@apple.com69caeee2018-04-20 04:55:32 +00002006 pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>", cachedPage.get());
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00002007
wenson_hsieh@apple.com2851e662020-08-10 02:18:44 +00002008 if (auto document = makeRefPtr(m_frame.document())) {
2009 // In the case where we're restoring from a cached page, our document will not
2010 // be connected to its frame yet, so the following call with be a no-op. We will
2011 // attempt to confirm any active composition once again in this scenario after we
2012 // finish restoring from the cached page.
2013 document->editor().confirmCompositionAndNotifyClient();
2014 }
ap@apple.come042b632013-05-17 20:04:43 +00002015
cdumez@apple.coma0010ff2018-12-13 23:17:44 +00002016 if (!m_frame.tree().parent() && history().currentItem() && history().currentItem() != history().provisionalItem()) {
akling@apple.comaf7f33b2016-02-06 17:00:30 +00002017 // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
2018 // We are doing this here because we know for sure that a new page is about to be loaded.
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00002019 BackForwardCache::singleton().addIfCacheable(*history().currentItem(), m_frame.page());
cdumez@apple.com8420ada2016-06-21 17:05:48 +00002020
carlosgc@webkit.org32a60dd2016-11-10 14:24:26 +00002021 WebCore::jettisonExpensiveObjectsOnTopLevelNavigation();
akling@apple.comaf7f33b2016-02-06 17:00:30 +00002022 }
2023
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002024 if (m_loadType != FrameLoadType::Replace)
beidson50c3bd82007-01-03 03:11:18 +00002025 closeOldDataSources();
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00002026
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00002027 if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002028 m_client->makeRepresentation(pdl.get());
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00002029
akling@apple.com9663f4b2013-09-05 21:25:32 +00002030 transitionToCommitted(cachedPage.get());
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00002031
abarth@webkit.orgf12783f2012-10-03 19:34:30 +00002032 if (pdl && m_documentLoader) {
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00002033 // Check if the destination page is allowed to access the previous page's timing information.
akling@apple.com6eea45d2014-12-17 01:48:38 +00002034 Ref<SecurityOrigin> securityOrigin(SecurityOrigin::create(pdl->request().url()));
akling@apple.com5a7607f2015-01-21 22:33:49 +00002035 m_documentLoader->timing().setHasSameOriginAsPreviousDocument(securityOrigin.get().canRequest(m_previousURL));
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00002036 }
2037
beidsonb72fe2e2007-05-03 21:35:24 +00002038 // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
beidson50c3bd82007-01-03 03:11:18 +00002039 // status has changed, if there was a redirect. The frame load delegate may have saved some state about
2040 // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are
2041 // just about to commit a new page, there cannot possibly be a pending redirect at this point.
2042 if (m_sentRedirectNotification)
achristensen@apple.com6fddc912018-10-18 21:16:52 +00002043 clientRedirectCancelledOrFinished(NewLoadInProgress::No);
beidson50c3bd82007-01-03 03:11:18 +00002044
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00002045 if (cachedPage && cachedPage->document()) {
ap@apple.com1e8475922018-10-18 21:38:50 +00002046#if PLATFORM(IOS_FAMILY)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002047 // FIXME: CachedPage::restore() would dispatch viewport change notification. However UIKit expects load
2048 // commit to happen before any changes to viewport arguments and dealing with this there is difficult.
2049 m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true);
2050#endif
dbates@webkit.orgcd75cb62017-03-15 22:44:59 +00002051 willRestoreFromCachedPage();
commit-queue@webkit.orgcbb6a492010-09-20 20:20:25 +00002052
carlosgc@webkit.org72eb7962016-01-12 08:23:36 +00002053 // Start request for the main resource and dispatch didReceiveResponse before the load is committed for
2054 // consistency with all other loads. See https://bugs.webkit.org/show_bug.cgi?id=150927.
2055 ResourceError mainResouceError;
2056 unsigned long mainResourceIdentifier;
2057 ResourceRequest mainResourceRequest(cachedPage->documentLoader()->request());
2058 requestFromDelegate(mainResourceRequest, mainResourceIdentifier, mainResouceError);
2059 notifier().dispatchDidReceiveResponse(cachedPage->documentLoader(), mainResourceIdentifier, cachedPage->documentLoader()->response());
2060
commit-queue@webkit.org511a9492020-03-12 18:28:40 +00002061 auto hasInsecureContent = cachedPage->cachedMainFrame()->hasInsecureContent();
commit-queue@webkit.orgfbfef682020-03-14 02:10:54 +00002062 auto usedLegacyTLS = cachedPage->cachedMainFrame()->usedLegacyTLS();
beidson@apple.com4322db02016-09-16 00:27:11 +00002063
achristensen@apple.come0301a32020-02-07 23:30:29 +00002064 dispatchDidCommitLoad(hasInsecureContent, usedLegacyTLS);
cdumez@apple.com5c7c1f32019-01-16 20:40:02 +00002065
dbates@webkit.org1fecb922017-03-25 01:13:23 +00002066 // FIXME: This API should be turned around so that we ground CachedPage into the Page.
2067 cachedPage->restore(*m_frame.page());
commit-queue@webkit.org1686e5d2012-10-19 23:13:08 +00002068
ap@apple.com1e8475922018-10-18 21:38:50 +00002069#if PLATFORM(IOS_FAMILY)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002070 m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
2071 m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
2072#endif
wenson_hsieh@apple.com0c724172018-05-15 01:07:36 +00002073 m_frame.page()->chrome().dispatchDisabledAdaptationsDidChange(m_frame.page()->disabledAdaptations());
darin@apple.com961f2a52016-12-31 09:51:29 +00002074
2075 auto& title = m_documentLoader->title();
2076 if (!title.string.isNull())
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002077 m_client->dispatchDidReceiveTitle(title);
commit-queue@webkit.orgcbb6a492010-09-20 20:20:25 +00002078
carlosgc@webkit.org72eb7962016-01-12 08:23:36 +00002079 // Send remaining notifications for the main resource.
2080 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), mainResourceIdentifier, mainResourceRequest, ResourceResponse(),
2081 nullptr, static_cast<int>(m_documentLoader->response().expectedContentLength()), 0, mainResouceError);
2082
cdumez@apple.com81d062f2020-06-29 16:32:33 +00002083 Vector<Ref<Frame>> targetFrames;
2084 targetFrames.append(m_frame);
2085 for (auto* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
2086 targetFrames.append(*child);
2087
2088 for (auto& frame : targetFrames)
2089 frame->loader().checkCompleted();
akling@apple.com9663f4b2013-09-05 21:25:32 +00002090 } else
abarth@webkit.org55d49da2011-06-20 23:32:54 +00002091 didOpenURL();
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00002092
wenson_hsieh@apple.com2851e662020-08-10 02:18:44 +00002093 if (auto document = makeRefPtr(m_frame.document()))
2094 document->editor().confirmCompositionAndNotifyClient();
2095
darin@apple.comfed4d162013-08-25 02:28:06 +00002096 LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame.tree().uniqueName().string().utf8().data(),
akling@apple.com7f50aae2013-08-22 16:01:31 +00002097 m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "");
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00002098
Hironori.Fujii@sony.com2253a9d2018-07-02 01:52:14 +00002099 if (m_loadType == FrameLoadType::Standard && m_documentLoader && m_documentLoader->isClientRedirect())
akling@apple.com672cb852013-08-22 20:27:27 +00002100 history().updateForClientRedirect();
beidson@apple.com028c7a72009-02-11 22:01:22 +00002101
beidson@apple.comac095c02009-08-18 01:37:56 +00002102 if (m_loadingFromCachedPage) {
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002103 // Note, didReceiveDocType is expected to be called for cached pages. See <rdar://problem/5906758> for more details.
darin@apple.com9ace8012017-01-23 06:24:18 +00002104 if (auto* page = m_frame.page())
2105 page->chrome().didReceiveDocType(m_frame);
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00002106 m_frame.document()->resume(ReasonForSuspension::BackForwardCache);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002107
beidson@apple.com028c7a72009-02-11 22:01:22 +00002108 // Force a layout to update view size and thereby update scrollbars.
ap@apple.com1e8475922018-10-18 21:38:50 +00002109#if PLATFORM(IOS_FAMILY)
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002110 if (!m_client->forceLayoutOnRestoreFromBackForwardCache())
simon.fraser@apple.com72978b32014-03-09 18:14:07 +00002111 m_frame.view()->forceLayout();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002112#else
akling@apple.com7f50aae2013-08-22 16:01:31 +00002113 m_frame.view()->forceLayout();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002114#endif
beidson@apple.com028c7a72009-02-11 22:01:22 +00002115
carlosgc@webkit.org72eb7962016-01-12 08:23:36 +00002116 // Main resource delegates were already sent, so we skip the first response here.
2117 for (unsigned i = 1; i < m_documentLoader->responses().size(); ++i) {
2118 const auto& response = m_documentLoader->responses()[i];
beidson@apple.com028c7a72009-02-11 22:01:22 +00002119 // FIXME: If the WebKit client changes or cancels the request, this is not respected.
2120 ResourceError error;
2121 unsigned long identifier;
2122 ResourceRequest request(response.url());
2123 requestFromDelegate(request, identifier, error);
2124 // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
2125 // However, with today's computers and networking speeds, this won't happen in practice.
2126 // Could be an issue with a giant local file.
akling@apple.com654fd9a2013-10-06 21:07:29 +00002127 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, 0, static_cast<int>(response.expectedContentLength()), 0, error);
beidson@apple.com028c7a72009-02-11 22:01:22 +00002128 }
beidson@apple.com028c7a72009-02-11 22:01:22 +00002129
beidson@apple.com028c7a72009-02-11 22:01:22 +00002130 // FIXME: Why only this frame and not parent frames?
2131 checkLoadCompleteForThisFrame();
2132 }
beidson50c3bd82007-01-03 03:11:18 +00002133}
2134
akling@apple.com9663f4b2013-09-05 21:25:32 +00002135void FrameLoader::transitionToCommitted(CachedPage* cachedPage)
beidson50c3bd82007-01-03 03:11:18 +00002136{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002137 ASSERT(m_client->hasWebView());
beidson50c3bd82007-01-03 03:11:18 +00002138 ASSERT(m_state == FrameStateProvisional);
2139
2140 if (m_state != FrameStateProvisional)
2141 return;
2142
akling@apple.com7f50aae2013-08-22 16:01:31 +00002143 if (FrameView* view = m_frame.view()) {
bdakin@apple.com3fec69c2012-03-23 21:02:51 +00002144 if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
bdakin@apple.com87235fc2012-03-23 20:36:31 +00002145 scrollAnimator->cancelAnimations();
2146 }
bdakin@apple.come0a38ad2011-03-15 18:30:41 +00002147
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002148 m_client->setCopiesOnScroll();
akling@apple.com672cb852013-08-22 20:27:27 +00002149 history().updateForCommit();
beidson50c3bd82007-01-03 03:11:18 +00002150
2151 // The call to closeURL() invokes the unload event handler, which can execute arbitrary
2152 // JavaScript. If the script initiates a new load, we need to abandon the current load,
2153 // or the two will stomp each other.
darin@apple.com325c5bdc2020-05-07 18:55:50 +00002154 auto originalProvisionalDocumentLoader = m_provisionalDocumentLoader;
mjs8d620d52007-05-10 12:31:42 +00002155 if (m_documentLoader)
2156 closeURL();
darin@apple.com325c5bdc2020-05-07 18:55:50 +00002157 if (originalProvisionalDocumentLoader != m_provisionalDocumentLoader)
beidson50c3bd82007-01-03 03:11:18 +00002158 return;
2159
beidson4a289132007-05-03 18:50:41 +00002160 if (m_documentLoader)
2161 m_documentLoader->stopLoadingSubresources();
2162 if (m_documentLoader)
2163 m_documentLoader->stopLoadingPlugIns();
2164
dbates@webkit.orgd77aa3f2017-05-03 16:58:04 +00002165 // Setting our document loader invokes the unload event handler of our child frames.
2166 // Script can do anything. If the script initiates a new load, we need to abandon the
2167 // current load or the two will stomp each other.
beidson4a289132007-05-03 18:50:41 +00002168 setDocumentLoader(m_provisionalDocumentLoader.get());
darin@apple.com325c5bdc2020-05-07 18:55:50 +00002169 if (originalProvisionalDocumentLoader != m_provisionalDocumentLoader)
dbates@webkit.orgd77aa3f2017-05-03 16:58:04 +00002170 return;
krollin@apple.combdeaed72020-01-08 01:31:20 +00002171 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "transitionToCommitted: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002172 setProvisionalDocumentLoader(nullptr);
japhet@chromium.orga9a58bb2012-09-01 01:09:02 +00002173
dbates@webkit.orgec907882017-05-05 04:04:35 +00002174 // Nothing else can interrupt this commit - set the Provisional->Committed transition in stone
commit-queue@webkit.org1af3b432011-08-05 07:00:47 +00002175 setState(FrameStateCommittedPage);
beidson50c3bd82007-01-03 03:11:18 +00002176
2177 // Handle adding the URL to the back/forward list.
darin@apple.com325c5bdc2020-05-07 18:55:50 +00002178 auto documentLoader = m_documentLoader;
beidson50c3bd82007-01-03 03:11:18 +00002179
2180 switch (m_loadType) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002181 case FrameLoadType::Forward:
2182 case FrameLoadType::Back:
2183 case FrameLoadType::IndexedBackForward:
2184 if (m_frame.page()) {
2185 // If the first load within a frame is a navigation within a back/forward list that was attached
2186 // without any of the items being loaded then we need to update the history in a similar manner as
2187 // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
2188 if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame.isMainFrame())
2189 history().updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
mrowe@apple.com04fa4872010-06-16 02:23:45 +00002190
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002191 history().updateForBackForwardNavigation();
beidson50c3bd82007-01-03 03:11:18 +00002192
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002193 // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
2194 if (history().currentItem() && !cachedPage)
2195 m_pendingStateObject = history().currentItem()->stateObject();
mrowe@apple.com04fa4872010-06-16 02:23:45 +00002196
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002197 // Create a document view for this document, or used the cached view.
2198 if (cachedPage) {
darin@apple.com325c5bdc2020-05-07 18:55:50 +00002199 ASSERT(cachedPage->documentLoader());
2200 cachedPage->documentLoader()->attachToFrame(m_frame);
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002201 m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002202 } else
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002203 m_client->transitionToCommittedForNewPage();
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002204 }
2205 break;
beidson50c3bd82007-01-03 03:11:18 +00002206
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002207 case FrameLoadType::Reload:
2208 case FrameLoadType::ReloadFromOrigin:
antti@apple.com5d0c5402017-03-17 19:52:49 +00002209 case FrameLoadType::ReloadExpiredOnly:
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002210 case FrameLoadType::Same:
2211 case FrameLoadType::Replace:
2212 history().updateForReload();
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002213 m_client->transitionToCommittedForNewPage();
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002214 break;
beidson50c3bd82007-01-03 03:11:18 +00002215
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002216 case FrameLoadType::Standard:
2217 history().updateForStandardLoad();
2218 if (m_frame.view())
2219 m_frame.view()->setScrollbarsSuppressed(true);
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002220 m_client->transitionToCommittedForNewPage();
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002221 break;
beidson50c3bd82007-01-03 03:11:18 +00002222
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002223 case FrameLoadType::RedirectWithLockedBackForwardList:
2224 history().updateForRedirectWithLockedBackForwardList();
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002225 m_client->transitionToCommittedForNewPage();
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002226 break;
beidson50c3bd82007-01-03 03:11:18 +00002227 }
2228
darin@apple.com325c5bdc2020-05-07 18:55:50 +00002229 if (documentLoader)
2230 documentLoader->writer().setMIMEType(documentLoader->responseMIMEType());
mjs8d620d52007-05-10 12:31:42 +00002231
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00002232 if (m_stateMachine.creatingInitialEmptyDocument())
mjs8d620d52007-05-10 12:31:42 +00002233 return;
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00002234
2235 if (!m_stateMachine.committedFirstRealDocumentLoad())
2236 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
beidson50c3bd82007-01-03 03:11:18 +00002237}
2238
achristensen@apple.com6fddc912018-10-18 21:16:52 +00002239void FrameLoader::clientRedirectCancelledOrFinished(NewLoadInProgress newLoadInProgress)
darinc370e7e2006-11-08 05:52:27 +00002240{
2241 // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
2242 // the redirect succeeded. We should either rename this API, or add a new method, like
2243 // -webView:didFinishClientRedirectForFrame:
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002244 m_client->dispatchDidCancelClientRedirect();
darinc370e7e2006-11-08 05:52:27 +00002245
achristensen@apple.com6fddc912018-10-18 21:16:52 +00002246 if (newLoadInProgress == NewLoadInProgress::No)
darinc370e7e2006-11-08 05:52:27 +00002247 m_quickRedirectComing = false;
2248
2249 m_sentRedirectNotification = false;
2250}
2251
utatane.tea@gmail.comeb3a8092018-02-23 04:18:17 +00002252void FrameLoader::clientRedirected(const URL& url, double seconds, WallTime fireDate, LockBackForwardList lockBackForwardList)
darinc370e7e2006-11-08 05:52:27 +00002253{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002254 m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate, lockBackForwardList);
darinc370e7e2006-11-08 05:52:27 +00002255
2256 // Remember that we sent a redirect notification to the frame load delegate so that when we commit
2257 // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
2258 m_sentRedirectNotification = true;
2259
darin@apple.com0f88bda2009-04-02 00:30:50 +00002260 // If a "quick" redirect comes in, we set a special mode so we treat the next
2261 // load as part of the original navigation. If we don't have a document loader, we have
darinc370e7e2006-11-08 05:52:27 +00002262 // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
darin@apple.com0f88bda2009-04-02 00:30:50 +00002263 // Loads triggered by JavaScript form submissions never count as quick redirects.
mrowe@apple.combf5eaa62014-04-03 00:51:04 +00002264 m_quickRedirectComing = (lockBackForwardList == LockBackForwardList::Yes || history().currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
darinc370e7e2006-11-08 05:52:27 +00002265}
2266
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002267bool FrameLoader::shouldReload(const URL& currentURL, const URL& destinationURL)
darinc370e7e2006-11-08 05:52:27 +00002268{
2269 // This function implements the rule: "Don't reload if navigating by fragment within
2270 // the same URL, but do reload if going to a new URL or to the same URL with no
2271 // fragment identifier at all."
beidson@apple.comee497252009-08-10 16:35:00 +00002272 if (!destinationURL.hasFragmentIdentifier())
darinc370e7e2006-11-08 05:52:27 +00002273 return true;
beidson@apple.comee497252009-08-10 16:35:00 +00002274 return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
darinc370e7e2006-11-08 05:52:27 +00002275}
2276
2277void FrameLoader::closeOldDataSources()
2278{
2279 // FIXME: Is it important for this traversal to be postorder instead of preorder?
2280 // If so, add helpers for postorder traversal, and use them. If not, then lets not
2281 // use a recursive algorithm here.
darin@apple.comfed4d162013-08-25 02:28:06 +00002282 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
andersca@apple.comdf550b92013-08-15 22:17:17 +00002283 child->loader().closeOldDataSources();
darinc370e7e2006-11-08 05:52:27 +00002284
2285 if (m_documentLoader)
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002286 m_client->dispatchWillClose();
darinc370e7e2006-11-08 05:52:27 +00002287
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002288 m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
darinc370e7e2006-11-08 05:52:27 +00002289}
2290
dbates@webkit.orgcd75cb62017-03-15 22:44:59 +00002291void FrameLoader::willRestoreFromCachedPage()
darinc370e7e2006-11-08 05:52:27 +00002292{
darin@apple.comfed4d162013-08-25 02:28:06 +00002293 ASSERT(!m_frame.tree().parent());
akling@apple.com7f50aae2013-08-22 16:01:31 +00002294 ASSERT(m_frame.page());
darin@apple.com0e83ab12013-09-28 17:19:04 +00002295 ASSERT(m_frame.isMainFrame());
darinc370e7e2006-11-08 05:52:27 +00002296
akling@apple.com7f50aae2013-08-22 16:01:31 +00002297 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +00002298
2299 // We still have to close the previous part page.
2300 closeURL();
darinc370e7e2006-11-08 05:52:27 +00002301
2302 // Delete old status bar messages (if it _was_ activated on last URL).
akling@apple.com7f50aae2013-08-22 16:01:31 +00002303 if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) {
2304 DOMWindow* window = m_frame.document()->domWindow();
abarth@webkit.org13fe1e22012-08-16 22:29:48 +00002305 window->setStatus(String());
2306 window->setDefaultStatus(String());
darinc370e7e2006-11-08 05:52:27 +00002307 }
beidson@apple.com028c7a72009-02-11 22:01:22 +00002308}
2309
beidson@apple.com913c7f82009-09-02 20:16:38 +00002310void FrameLoader::open(CachedFrameBase& cachedFrame)
beidson@apple.com028c7a72009-02-11 22:01:22 +00002311{
beidson@apple.com028c7a72009-02-11 22:01:22 +00002312 // Don't re-emit the load event.
2313 m_didCallImplicitClose = true;
2314
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002315 URL url = cachedFrame.url();
darinc370e7e2006-11-08 05:52:27 +00002316
abarth@webkit.org55d49da2011-06-20 23:32:54 +00002317 // FIXME: I suspect this block of code doesn't do anything.
benjamin@webkit.orgf726d632012-03-04 03:26:27 +00002318 if (url.protocolIsInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
weinig@apple.comc5002662007-12-12 07:26:19 +00002319 url.setPath("/");
abarth@webkit.org55d49da2011-06-20 23:32:54 +00002320
abarth@webkit.org91289c32010-04-12 04:54:55 +00002321 started();
rniwa@webkit.org77c65702019-08-13 05:18:11 +00002322 auto document = makeRef(*cachedFrame.document());
abarth@webkit.org23ea90a2012-08-14 19:47:59 +00002323 ASSERT(document->domWindow());
2324
rniwa@webkit.org77c65702019-08-13 05:18:11 +00002325 clear(document.ptr(), true, true, cachedFrame.isMainFrame());
abarth@webkit.org23ea90a2012-08-14 19:47:59 +00002326
cdumez@apple.comf0705d72019-07-01 21:55:03 +00002327 document->attachToCachedFrame(cachedFrame);
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00002328 document->setBackForwardCacheState(Document::NotInBackForwardCache);
darinc370e7e2006-11-08 05:52:27 +00002329
2330 m_needsClear = true;
2331 m_isComplete = false;
ggarena57755c2007-07-09 21:08:10 +00002332 m_didCallImplicitClose = false;
Hironori.Fujii@sony.com27c57b42019-08-28 01:40:42 +00002333 setOutgoingReferrer(url);
kmccullo6b1b5c22007-05-24 20:06:56 +00002334
beidson@apple.com028c7a72009-02-11 22:01:22 +00002335 FrameView* view = cachedFrame.view();
2336
2337 // When navigating to a CachedFrame its FrameView should never be null. If it is we'll crash in creative ways downstream.
2338 ASSERT(view);
beidson@apple.com24f92a52009-09-03 00:07:51 +00002339 view->setWasScrolledByUser(false);
adachan@apple.com95f492a2009-08-24 19:55:23 +00002340
cdumez@apple.com8b7a0222018-12-20 04:41:11 +00002341 Optional<IntRect> previousViewFrameRect = m_frame.view() ? m_frame.view()->frameRect() : Optional<IntRect>(WTF::nullopt);
akling@apple.com7f50aae2013-08-22 16:01:31 +00002342 m_frame.setView(view);
cdumez@apple.com665ca3b2015-05-08 18:15:57 +00002343
2344 // Use the previous ScrollView's frame rect.
2345 if (previousViewFrameRect)
2346 view->setFrameRect(previousViewFrameRect.value());
dbates@webkit.org7259cf32018-08-21 16:50:20 +00002347
rniwa@webkit.org77c65702019-08-13 05:18:11 +00002348
2349 // Setting the document builds the render tree and runs post style resolution callbacks that can do anything,
2350 // including loading a child frame before its been re-attached to the frame tree as part of this restore.
2351 // For example, the HTML object element may load its content into a frame in a post style resolution callback.
2352 Style::PostResolutionCallbackDisabler disabler(document.get());
2353 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
2354 NavigationDisabler disableNavigation { &m_frame };
2355
2356 m_frame.setDocument(document.copyRef());
dbates@webkit.org7259cf32018-08-21 16:50:20 +00002357
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00002358 document->domWindow()->resumeFromBackForwardCache();
weinig@apple.com5367c412008-06-27 00:03:25 +00002359
abarth@webkit.org622d9df2009-05-22 16:44:47 +00002360 updateFirstPartyForCookies();
darinc370e7e2006-11-08 05:52:27 +00002361
beidson@apple.com028c7a72009-02-11 22:01:22 +00002362 cachedFrame.restore();
darinc370e7e2006-11-08 05:52:27 +00002363}
2364
darinc370e7e2006-11-08 05:52:27 +00002365bool FrameLoader::isReplacing() const
2366{
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002367 return m_loadType == FrameLoadType::Replace;
darinc370e7e2006-11-08 05:52:27 +00002368}
2369
2370void FrameLoader::setReplacing()
2371{
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002372 m_loadType = FrameLoadType::Replace;
darinc370e7e2006-11-08 05:52:27 +00002373}
2374
darinc370e7e2006-11-08 05:52:27 +00002375bool FrameLoader::subframeIsLoading() const
2376{
2377 // It's most likely that the last added frame is the last to load so we walk backwards.
darin@apple.comfed4d162013-08-25 02:28:06 +00002378 for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) {
andersca@apple.comdf550b92013-08-15 22:17:17 +00002379 FrameLoader& childLoader = child->loader();
2380 DocumentLoader* documentLoader = childLoader.documentLoader();
darinc370e7e2006-11-08 05:52:27 +00002381 if (documentLoader && documentLoader->isLoadingInAPISense())
2382 return true;
andersca@apple.comdf550b92013-08-15 22:17:17 +00002383 documentLoader = childLoader.provisionalDocumentLoader();
darinc370e7e2006-11-08 05:52:27 +00002384 if (documentLoader && documentLoader->isLoadingInAPISense())
2385 return true;
andersca@apple.comdf550b92013-08-15 22:17:17 +00002386 documentLoader = childLoader.policyDocumentLoader();
mjs@apple.com17a175d2010-07-18 00:15:31 +00002387 if (documentLoader)
2388 return true;
darinc370e7e2006-11-08 05:52:27 +00002389 }
2390 return false;
2391}
2392
2393void FrameLoader::willChangeTitle(DocumentLoader* loader)
2394{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002395 m_client->willChangeTitle(loader);
darinc370e7e2006-11-08 05:52:27 +00002396}
2397
2398FrameLoadType FrameLoader::loadType() const
2399{
2400 return m_loadType;
2401}
antti@apple.com4da613e2008-12-15 15:28:41 +00002402
antti@apple.com2b38ed12017-04-26 18:22:27 +00002403CachePolicy FrameLoader::subresourceCachePolicy(const URL& url) const
antti@apple.com4da613e2008-12-15 15:28:41 +00002404{
darin@apple.com30c194a2016-03-20 20:08:59 +00002405 if (Page* page = m_frame.page()) {
cdumez@apple.coma231c912019-10-16 18:24:25 +00002406 if (page->isResourceCachingDisabledByWebInspector())
darin@apple.com30c194a2016-03-20 20:08:59 +00002407 return CachePolicyReload;
2408 }
darin@apple.com0fdefc32016-03-18 07:56:20 +00002409
antti@apple.com4da613e2008-12-15 15:28:41 +00002410 if (m_isComplete)
2411 return CachePolicyVerify;
ap@webkit.org86b10982009-05-18 15:30:10 +00002412
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002413 if (m_loadType == FrameLoadType::ReloadFromOrigin)
antti@apple.com4da613e2008-12-15 15:28:41 +00002414 return CachePolicyReload;
ap@webkit.org86b10982009-05-18 15:30:10 +00002415
darin@apple.comfed4d162013-08-25 02:28:06 +00002416 if (Frame* parentFrame = m_frame.tree().parent()) {
antti@apple.com2b38ed12017-04-26 18:22:27 +00002417 CachePolicy parentCachePolicy = parentFrame->loader().subresourceCachePolicy(url);
antti@apple.com4da613e2008-12-15 15:28:41 +00002418 if (parentCachePolicy != CachePolicyVerify)
2419 return parentCachePolicy;
2420 }
slewis@apple.comef236f42011-05-25 23:00:45 +00002421
cdumez@apple.com74493162014-12-08 18:42:12 +00002422 switch (m_loadType) {
2423 case FrameLoadType::Reload:
antti@apple.com4da613e2008-12-15 15:28:41 +00002424 return CachePolicyRevalidate;
cdumez@apple.com74493162014-12-08 18:42:12 +00002425 case FrameLoadType::Back:
2426 case FrameLoadType::Forward:
2427 case FrameLoadType::IndexedBackForward:
joepeck@webkit.org853e6862010-11-18 17:59:53 +00002428 return CachePolicyHistoryBuffer;
cdumez@apple.com74493162014-12-08 18:42:12 +00002429 case FrameLoadType::ReloadFromOrigin:
2430 ASSERT_NOT_REACHED(); // Already handled above.
2431 return CachePolicyReload;
2432 case FrameLoadType::RedirectWithLockedBackForwardList:
2433 case FrameLoadType::Replace:
2434 case FrameLoadType::Same:
2435 case FrameLoadType::Standard:
antti@apple.com2b38ed12017-04-26 18:22:27 +00002436 return CachePolicyVerify;
antti@apple.com5d0c5402017-03-17 19:52:49 +00002437 case FrameLoadType::ReloadExpiredOnly:
antti@apple.com2b38ed12017-04-26 18:22:27 +00002438 // We know about expiration for HTTP and data. Do a normal reload otherwise.
2439 if (!url.protocolIsInHTTPFamily() && !url.protocolIsData())
2440 return CachePolicyReload;
cdumez@apple.com74493162014-12-08 18:42:12 +00002441 return CachePolicyVerify;
2442 }
ossy@webkit.org41788ca2014-12-08 19:30:19 +00002443
2444 RELEASE_ASSERT_NOT_REACHED();
2445 return CachePolicyVerify;
antti@apple.com4da613e2008-12-15 15:28:41 +00002446}
darinc370e7e2006-11-08 05:52:27 +00002447
aestes@apple.com5a4908d2019-06-07 06:09:40 +00002448void FrameLoader::dispatchDidFailProvisionalLoad(DocumentLoader& provisionalDocumentLoader, const ResourceError& error)
2449{
2450 m_provisionalLoadErrorBeingHandledURL = provisionalDocumentLoader.url();
2451
2452#if ENABLE(CONTENT_FILTERING)
2453 auto contentFilter = provisionalDocumentLoader.contentFilter();
2454 auto contentFilterWillContinueLoading = false;
2455#endif
2456
2457 auto willContinueLoading = WillContinueLoading::No;
2458 if (history().provisionalItem())
2459 willContinueLoading = WillContinueLoading::Yes;
2460#if ENABLE(CONTENT_FILTERING)
2461 if (contentFilter && contentFilter->willHandleProvisionalLoadFailure(error)) {
2462 willContinueLoading = WillContinueLoading::Yes;
2463 contentFilterWillContinueLoading = true;
2464 }
2465#endif
2466
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002467 m_client->dispatchDidFailProvisionalLoad(error, willContinueLoading);
aestes@apple.com5a4908d2019-06-07 06:09:40 +00002468
2469#if ENABLE(CONTENT_FILTERING)
2470 if (contentFilterWillContinueLoading)
2471 contentFilter->handleProvisionalLoadFailure(error);
2472#endif
2473
2474 m_provisionalLoadErrorBeingHandledURL = { };
2475}
2476
andersca4422e372007-01-12 19:56:19 +00002477void FrameLoader::checkLoadCompleteForThisFrame()
2478{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002479 ASSERT(m_client->hasWebView());
andersca4422e372007-01-12 19:56:19 +00002480
darin@apple.combe4d3dd2017-07-30 21:44:01 +00002481 // FIXME: Should this check be done in checkLoadComplete instead of here?
2482 // FIXME: Why does this one check need to be repeated here, and not the many others from checkCompleted?
2483 if (m_frame.document()->isDelayingLoadEvent())
2484 return;
2485
andersca4422e372007-01-12 19:56:19 +00002486 switch (m_state) {
2487 case FrameStateProvisional: {
jiewen_tan@apple.com8c36f622016-04-01 21:40:20 +00002488 // FIXME: Prohibiting any provisional load failures from being sent to clients
2489 // while handling provisional load failures is too heavy. For example, the current
2490 // load will fail to cancel another ongoing load. That might prevent clients' page
2491 // load state being handled properly.
mitz@apple.com6699e272015-05-01 23:47:03 +00002492 if (!m_provisionalLoadErrorBeingHandledURL.isEmpty())
andersca4422e372007-01-12 19:56:19 +00002493 return;
2494
2495 RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2496 if (!pdl)
2497 return;
2498
2499 // If we've received any errors we may be stuck in the provisional state and actually complete.
2500 const ResourceError& error = pdl->mainDocumentError();
2501 if (error.isNull())
2502 return;
2503
2504 // Check all children first.
2505 RefPtr<HistoryItem> item;
akling@apple.com7f50aae2013-08-22 16:01:31 +00002506 if (Page* page = m_frame.page())
commit-queue@webkit.org21a48d82011-01-09 01:27:19 +00002507 if (isBackForwardLoadType(loadType()))
2508 // Reset the back forward list to the last committed history item at the top level.
akling@apple.com095b5442013-08-27 02:47:37 +00002509 item = page->mainFrame().loader().history().currentItem();
andersca4422e372007-01-12 19:56:19 +00002510
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00002511 // Only reset if we aren't already going to a new provisional item.
akling@apple.com672cb852013-08-22 20:27:27 +00002512 bool shouldReset = !history().provisionalItem();
ap@apple.com421e9a12011-03-24 00:50:45 +00002513 if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00002514 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "checkLoadCompleteForThisFrame: Failed provisional load (isTimeout = %d, isCancellation = %d, errorCode = %d)", error.isTimeout(), error.isCancellation(), error.errorCode());
cdumez@apple.com41883a92019-04-23 15:38:11 +00002515
aestes@apple.com5a4908d2019-06-07 06:09:40 +00002516 dispatchDidFailProvisionalLoad(*pdl, error);
ap@apple.com09535d12011-03-24 00:48:30 +00002517 ASSERT(!pdl->isLoading());
andersca4422e372007-01-12 19:56:19 +00002518
eric@webkit.orgb562c402010-01-13 01:29:35 +00002519 // If we're in the middle of loading multipart data, we need to restore the document loader.
2520 if (isReplacing() && !m_documentLoader.get())
eric@webkit.org90747252010-01-12 18:10:14 +00002521 setDocumentLoader(m_provisionalDocumentLoader.get());
2522
andersca4422e372007-01-12 19:56:19 +00002523 // Finish resetting the load state, but only if another load hasn't been started by the
2524 // delegate callback.
2525 if (pdl == m_provisionalDocumentLoader)
2526 clearProvisionalLoad();
tonikitoo@webkit.orge94ac9b2009-11-16 15:38:19 +00002527 else if (activeDocumentLoader()) {
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002528 URL unreachableURL = activeDocumentLoader()->unreachableURL();
andersca4422e372007-01-12 19:56:19 +00002529 if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2530 shouldReset = false;
2531 }
2532 }
darine0cef432007-07-10 19:21:23 +00002533 if (shouldReset && item)
akling@apple.com7f50aae2013-08-22 16:01:31 +00002534 if (Page* page = m_frame.page()) {
achristensen@apple.com3a889f12018-10-16 15:58:10 +00002535 page->backForward().setCurrentItem(*item);
mitz@apple.combc843762008-12-08 21:18:11 +00002536 }
andersca4422e372007-01-12 19:56:19 +00002537 return;
2538 }
2539
2540 case FrameStateCommittedPage: {
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +00002541 if (!m_documentLoader)
2542 return;
2543 if (m_documentLoader->isLoadingInAPISense() && !m_documentLoader->isStopping() && !m_checkingLoadCompleteForDetachment)
andersca4422e372007-01-12 19:56:19 +00002544 return;
2545
darin@apple.comaf8b1a92011-06-25 00:09:37 +00002546 setState(FrameStateComplete);
andersca4422e372007-01-12 19:56:19 +00002547
2548 // FIXME: Is this subsequent work important if we already navigated away?
2549 // Maybe there are bugs because of that, or extra work we can skip because
2550 // the new page is ready.
2551
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002552 m_client->forceLayoutForNonHTML();
andersca4422e372007-01-12 19:56:19 +00002553
2554 // If the user had a scroll point, scroll to it, overriding the anchor point if any.
akling@apple.com7f50aae2013-08-22 16:01:31 +00002555 if (m_frame.page()) {
antti@apple.com5d0c5402017-03-17 19:52:49 +00002556 if (isBackForwardLoadType(m_loadType) || isReload(m_loadType))
akling@apple.com672cb852013-08-22 20:27:27 +00002557 history().restoreScrollPositionAndViewState();
darin@apple.come10e1282010-10-30 00:44:33 +00002558 }
andersca4422e372007-01-12 19:56:19 +00002559
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00002560 if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
mjs8d620d52007-05-10 12:31:42 +00002561 return;
2562
timothy_horton@apple.com346f8d72013-08-01 00:06:51 +00002563 m_progressTracker->progressCompleted();
eric.carlson@apple.com77b4a112014-10-30 19:04:29 +00002564 Page* page = m_frame.page();
2565 if (page) {
simon.fraser@apple.com83325b92017-03-17 00:47:16 +00002566 if (m_frame.isMainFrame()) {
sbarati@apple.comce7ec112018-04-17 15:57:32 +00002567 tracePoint(MainResourceLoadDidEnd);
cdumez@apple.comef2c0152017-01-13 17:54:53 +00002568 page->didFinishLoad();
simon.fraser@apple.com83325b92017-03-17 00:47:16 +00002569 }
andersca@apple.com7c0a3fc2012-05-01 22:22:25 +00002570 }
2571
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +00002572 const ResourceError& error = m_documentLoader->mainDocumentError();
mario@webkit.org685258f2011-12-06 00:10:55 +00002573
2574 AXObjectCache::AXLoadingEvent loadingEvent;
2575 if (!error.isNull()) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00002576 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "checkLoadCompleteForThisFrame: Finished frame load with error (isTimeout = %d, isCancellation = %d, errorCode = %d)", error.isTimeout(), error.isCancellation(), error.errorCode());
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002577 m_client->dispatchDidFailLoad(error);
mario@webkit.org685258f2011-12-06 00:10:55 +00002578 loadingEvent = AXObjectCache::AXLoadingFailed;
2579 } else {
krollin@apple.combdeaed72020-01-08 01:31:20 +00002580 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "checkLoadCompleteForThisFrame: Finished frame load");
enrica@apple.com53b08e52016-01-19 22:58:59 +00002581#if ENABLE(DATA_DETECTION)
darin@apple.come729ead2020-04-27 15:05:00 +00002582 auto document = m_frame.document();
2583 auto types = m_frame.settings().dataDetectorTypes();
2584 if (document && static_cast<uint32_t>(types)) {
2585 m_frame.setDataDetectionResults(DataDetection::detectContentInRange(makeRangeSelectingNodeContents(*document), types, m_client->dataDetectionContext()));
2586 if (m_frame.isMainFrame())
2587 m_client->dispatchDidFinishDataDetection(m_frame.dataDetectionResults());
enrica@apple.com53b08e52016-01-19 22:58:59 +00002588 }
2589#endif
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002590 m_client->dispatchDidFinishLoad();
enrica@apple.com4c36ad52016-01-23 00:24:02 +00002591 loadingEvent = AXObjectCache::AXLoadingFinished;
mario@webkit.org685258f2011-12-06 00:10:55 +00002592 }
2593
2594 // Notify accessibility.
rniwa@webkit.org2f150e72016-06-14 07:35:53 +00002595 if (auto* document = m_frame.document()) {
2596 if (AXObjectCache* cache = document->existingAXObjectCache())
2597 cache->frameLoadingEventNotification(&m_frame, loadingEvent);
2598 }
andersca4422e372007-01-12 19:56:19 +00002599
beidson@apple.com4aecb3d2015-07-09 04:47:09 +00002600 // The above calls to dispatchDidFinishLoad() might have detached the Frame
2601 // from its Page and also might have caused Page to be deleted.
2602 // Don't assume 'page' is still available to use.
2603 if (m_frame.isMainFrame() && m_frame.page()) {
2604 ASSERT(&m_frame.page()->mainFrame() == &m_frame);
cdumez@apple.com10d0f252016-04-23 21:33:49 +00002605 m_frame.page()->diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageLoadedKey(), emptyString(), error.isNull() ? DiagnosticLoggingResultPass : DiagnosticLoggingResultFail, ShouldSample::Yes);
beidson@apple.com4aecb3d2015-07-09 04:47:09 +00002606 }
eric.carlson@apple.com77b4a112014-10-30 19:04:29 +00002607
andersca4422e372007-01-12 19:56:19 +00002608 return;
2609 }
2610
2611 case FrameStateComplete:
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002612 m_loadType = FrameLoadType::Standard;
beidson@apple.comd1418272009-01-30 17:30:47 +00002613 frameLoadCompleted();
andersca4422e372007-01-12 19:56:19 +00002614 return;
2615 }
2616
2617 ASSERT_NOT_REACHED();
2618}
andersca5d5f8022007-02-28 00:38:00 +00002619
ap@apple.com456d4652011-11-30 12:13:31 +00002620void FrameLoader::setOriginalURLForDownloadRequest(ResourceRequest& request)
2621{
jiewen_tan@apple.com82836202016-03-31 20:39:24 +00002622 // FIXME: Rename firstPartyForCookies back to mainDocumentURL. It was a mistake to think that it was only used for cookies.
2623 // The originalURL is defined as the URL of the page where the download was initiated.
jiewen_tan@apple.com65b38162016-12-22 00:04:11 +00002624 URL originalURL;
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002625 auto* initiator = m_frame.document();
2626 if (initiator) {
2627 originalURL = initiator->firstPartyForCookies();
jiewen_tan@apple.com65b38162016-12-22 00:04:11 +00002628 // If there is no main document URL, it means that this document is newly opened and just for download purpose.
2629 // In this case, we need to set the originalURL to this document's opener's main document URL.
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002630 if (originalURL.isEmpty() && opener() && opener()->document()) {
jiewen_tan@apple.com65b38162016-12-22 00:04:11 +00002631 originalURL = opener()->document()->firstPartyForCookies();
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002632 initiator = opener()->document();
2633 }
jiewen_tan@apple.com65b38162016-12-22 00:04:11 +00002634 }
jiewen_tan@apple.com82836202016-03-31 20:39:24 +00002635 // If the originalURL is the same as the requested URL, we are processing a download
2636 // initiated directly without a page and do not need to specify the originalURL.
2637 if (originalURL == request.url())
2638 request.setFirstPartyForCookies(URL());
2639 else
2640 request.setFirstPartyForCookies(originalURL);
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002641 addSameSiteInfoToRequestIfNeeded(request, initiator);
ap@apple.com456d4652011-11-30 12:13:31 +00002642}
2643
antti@apple.com8e03f742018-11-09 19:47:15 +00002644void FrameLoader::didReachLayoutMilestone(OptionSet<LayoutMilestone> milestones)
darinc370e7e2006-11-08 05:52:27 +00002645{
darin@apple.com0e83ab12013-09-28 17:19:04 +00002646 ASSERT(m_frame.isMainFrame());
bdakin@apple.com7ce7e1b2013-08-12 21:37:06 +00002647
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002648 m_client->dispatchDidReachLayoutMilestone(milestones);
bdakin@apple.com3ab37372012-02-01 21:52:41 +00002649}
2650
bdakin@apple.come98caf12012-09-25 23:08:03 +00002651void FrameLoader::didFirstLayout()
2652{
ap@apple.com1e8475922018-10-18 21:38:50 +00002653#if PLATFORM(IOS_FAMILY)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002654 // Only send layout-related delegate callbacks synchronously for the main frame to
2655 // avoid reentering layout for the main frame while delivering a layout-related delegate
2656 // callback for a subframe.
2657 if (&m_frame != &m_frame.page()->mainFrame())
2658 return;
2659#endif
akling@apple.com7f50aae2013-08-22 16:01:31 +00002660 if (m_frame.page() && isBackForwardLoadType(m_loadType))
akling@apple.com672cb852013-08-22 20:27:27 +00002661 history().restoreScrollPositionAndViewState();
bdakin@apple.come98caf12012-09-25 23:08:03 +00002662
2663 if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2664 m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2665}
2666
zalan@apple.comfc7ad742020-03-04 14:53:01 +00002667void FrameLoader::didReachVisuallyNonEmptyState()
2668{
2669 ASSERT(m_frame.isMainFrame());
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002670 m_client->dispatchDidReachVisuallyNonEmptyState();
zalan@apple.comfc7ad742020-03-04 14:53:01 +00002671}
2672
darinc370e7e2006-11-08 05:52:27 +00002673void FrameLoader::frameLoadCompleted()
2674{
beidson@apple.comd1418272009-01-30 17:30:47 +00002675 // Note: Can be called multiple times.
2676
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002677 m_client->frameLoadCompleted();
darinc370e7e2006-11-08 05:52:27 +00002678
akling@apple.com672cb852013-08-22 20:27:27 +00002679 history().updateForFrameLoadCompleted();
beidson@apple.comd1418272009-01-30 17:30:47 +00002680
darinc370e7e2006-11-08 05:52:27 +00002681 // After a canceled provisional load, firstLayoutDone is false.
2682 // Reset it to true if we're displaying a page.
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00002683 if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2684 m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
darinc370e7e2006-11-08 05:52:27 +00002685}
2686
darinc370e7e2006-11-08 05:52:27 +00002687void FrameLoader::detachChildren()
2688{
cdumez@apple.com8b478c62016-01-23 01:04:59 +00002689 // detachChildren() will fire the unload event in each subframe and the
2690 // HTML specification states that the parent document's ignore-opens-during-unload counter while
2691 // this event is being fired in its subframes:
2692 // https://html.spec.whatwg.org/multipage/browsers.html#unload-a-document
2693 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
2694
cdumez@apple.comf0705d72019-07-01 21:55:03 +00002695 // detachChildren() will fire the unload event in each subframe and the
2696 // HTML specification states that navigations should be prevented during the prompt to unload algorithm:
2697 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigate
2698 std::unique_ptr<NavigationDisabler> navigationDisabler;
2699 if (m_frame.isMainFrame())
ysuzuki@apple.com1d8e24d2019-08-19 06:59:40 +00002700 navigationDisabler = makeUnique<NavigationDisabler>(&m_frame);
cdumez@apple.comf0705d72019-07-01 21:55:03 +00002701
cdumez@apple.com6857a012017-03-02 23:43:09 +00002702 // Any subframe inserted by unload event handlers executed in the loop below will not get unloaded
2703 // because we create a copy of the subframes list before looping. Therefore, it would be unsafe to
2704 // allow loading of subframes at this point.
2705 SubframeLoadingDisabler subframeLoadingDisabler(m_frame.document());
2706
akling@apple.com72c1c362013-09-06 01:34:05 +00002707 Vector<Ref<Frame>, 16> childrenToDetach;
2708 childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
darin@apple.comfed4d162013-08-25 02:28:06 +00002709 for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
akling@apple.com72c1c362013-09-06 01:34:05 +00002710 childrenToDetach.uncheckedAppend(*child);
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00002711 for (auto& child : childrenToDetach)
2712 child->loader().detachFromParent();
darinc370e7e2006-11-08 05:52:27 +00002713}
2714
darin@apple.com9ace8012017-01-23 06:24:18 +00002715void FrameLoader::closeAndRemoveChild(Frame& child)
beidson@apple.com028c7a72009-02-11 22:01:22 +00002716{
darin@apple.com9ace8012017-01-23 06:24:18 +00002717 child.tree().detachFromParent();
beidson@apple.com028c7a72009-02-11 22:01:22 +00002718
darin@apple.com9ace8012017-01-23 06:24:18 +00002719 child.setView(nullptr);
darin@apple.com9ace8012017-01-23 06:24:18 +00002720 child.willDetachPage();
2721 child.detachFromPage();
beidson@apple.com028c7a72009-02-11 22:01:22 +00002722
darin@apple.comfed4d162013-08-25 02:28:06 +00002723 m_frame.tree().removeChild(child);
beidson@apple.com028c7a72009-02-11 22:01:22 +00002724}
2725
darin@apple.comaf8b1a92011-06-25 00:09:37 +00002726// Called every time a resource is completely loaded or an error is received.
darinc370e7e2006-11-08 05:52:27 +00002727void FrameLoader::checkLoadComplete()
2728{
darin@apple.comf53381b2009-09-23 23:27:01 +00002729 m_shouldCallCheckLoadComplete = false;
2730
akling@apple.com72c1c362013-09-06 01:34:05 +00002731 if (!m_frame.page())
2732 return;
2733
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002734 ASSERT(m_client->hasWebView());
darin@apple.com355b1522017-08-15 18:13:57 +00002735
anderscaa315d572007-03-13 01:09:53 +00002736 // FIXME: Always traversing the entire frame tree is a bit inefficient, but
2737 // is currently needed in order to null out the previous history item for all frames.
akling@apple.com72c1c362013-09-06 01:34:05 +00002738 Vector<Ref<Frame>, 16> frames;
darin@apple.com0e83ab12013-09-28 17:19:04 +00002739 for (Frame* frame = &m_frame.mainFrame(); frame; frame = frame->tree().traverseNext())
akling@apple.com72c1c362013-09-06 01:34:05 +00002740 frames.append(*frame);
2741
2742 // To process children before their parents, iterate the vector backwards.
jiewen_tan@apple.combe26fa32015-12-01 00:33:47 +00002743 for (auto frame = frames.rbegin(); frame != frames.rend(); ++frame) {
2744 if ((*frame)->page())
2745 (*frame)->loader().checkLoadCompleteForThisFrame();
2746 }
darinc370e7e2006-11-08 05:52:27 +00002747}
2748
2749int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2750{
2751 if (!recurse)
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +00002752 return m_frame.document()->cachedResourceLoader().requestCount();
darinc370e7e2006-11-08 05:52:27 +00002753
2754 int count = 0;
darin@apple.comfed4d162013-08-25 02:28:06 +00002755 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +00002756 count += frame->document()->cachedResourceLoader().requestCount();
darinc370e7e2006-11-08 05:52:27 +00002757 return count;
2758}
2759
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002760String FrameLoader::userAgent(const URL& url) const
darinc370e7e2006-11-08 05:52:27 +00002761{
drousso@apple.comc9a88bd2019-01-26 22:32:38 +00002762 String userAgent;
2763
rniwa@webkit.org15470912019-01-26 06:50:58 +00002764 if (auto* documentLoader = m_frame.mainFrame().loader().activeDocumentLoader()) {
rniwa@webkit.orgaf0b1ae2019-01-29 07:15:00 +00002765 if (m_frame.settings().needsSiteSpecificQuirks())
rniwa@webkit.org75b8f3e2019-12-04 04:28:10 +00002766 userAgent = documentLoader->customUserAgentAsSiteSpecificQuirks();
drousso@apple.comc9a88bd2019-01-26 22:32:38 +00002767 if (userAgent.isEmpty())
2768 userAgent = documentLoader->customUserAgent();
rniwa@webkit.org15470912019-01-26 06:50:58 +00002769 }
2770
drousso@apple.comc9a88bd2019-01-26 22:32:38 +00002771 InspectorInstrumentation::applyUserAgentOverride(m_frame, userAgent);
2772
2773 if (!userAgent.isEmpty())
2774 return userAgent;
2775
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002776 return m_client->userAgent(url);
rniwa@webkit.org15470912019-01-26 06:50:58 +00002777}
rniwa@webkit.org75b8f3e2019-12-04 04:28:10 +00002778
megan_gardner@apple.comde788db2018-12-19 20:21:31 +00002779String FrameLoader::navigatorPlatform() const
2780{
2781 if (auto* documentLoader = m_frame.mainFrame().loader().activeDocumentLoader()) {
2782 auto& customNavigatorPlatform = documentLoader->customNavigatorPlatform();
2783 if (!customNavigatorPlatform.isEmpty())
2784 return customNavigatorPlatform;
2785 }
2786 return String();
2787}
darinc370e7e2006-11-08 05:52:27 +00002788
ggaren@apple.com7a176e12015-11-12 01:48:27 +00002789void FrameLoader::dispatchOnloadEvents()
darinc370e7e2006-11-08 05:52:27 +00002790{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002791 m_client->dispatchDidDispatchOnloadEvents();
japhet@chromium.org92a952b2010-07-12 18:14:17 +00002792
darin@apple.comaf8b1a92011-06-25 00:09:37 +00002793 if (documentLoader())
ggaren@apple.com7a176e12015-11-12 01:48:27 +00002794 documentLoader()->dispatchOnloadEvents();
darinc370e7e2006-11-08 05:52:27 +00002795}
2796
2797void FrameLoader::frameDetached()
2798{
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +00002799 // Calling stopAllLoadersAndCheckCompleteness() can cause the frame to be deallocated, including the frame loader.
bfulgham@apple.com98845d92016-05-17 01:09:27 +00002800 Ref<Frame> protectedFrame(m_frame);
2801
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +00002802 if (m_checkTimer.isActive()) {
2803 m_checkTimer.stop();
2804 checkCompletenessNow();
2805 }
2806
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00002807 if (m_frame.document()->backForwardCacheState() != Document::InBackForwardCache) {
rniwa@webkit.org1a1b5202018-06-01 22:30:02 +00002808 stopAllLoadersAndCheckCompleteness();
dbates@webkit.org6d862de2017-02-11 02:53:53 +00002809 m_frame.document()->stopActiveDOMObjects();
2810 }
2811
darinc370e7e2006-11-08 05:52:27 +00002812 detachFromParent();
2813}
2814
ggarenc04b2c52006-11-30 21:06:14 +00002815void FrameLoader::detachFromParent()
darinc370e7e2006-11-08 05:52:27 +00002816{
dbates@webkit.org6d862de2017-02-11 02:53:53 +00002817 // Calling stopAllLoaders() can cause the frame to be deallocated, including the frame loader.
akling@apple.coma34e5222013-09-10 03:44:05 +00002818 Ref<Frame> protect(m_frame);
ggarenc04b2c52006-11-30 21:06:14 +00002819
ggarenacf28742006-12-27 07:38:18 +00002820 closeURL();
akling@apple.com672cb852013-08-22 20:27:27 +00002821 history().saveScrollPositionAndViewStateToItem(history().currentItem());
ggarenc04b2c52006-11-30 21:06:14 +00002822 detachChildren();
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00002823 if (m_frame.document()->backForwardCacheState() != Document::InBackForwardCache) {
2824 // stopAllLoaders() needs to be called after detachChildren() if the document is not in the back/forward cache,
dbates@webkit.org6d862de2017-02-11 02:53:53 +00002825 // because detachedChildren() will trigger the unload event handlers of any child frames, and those event
2826 // handlers might start a new subresource load in this frame.
ajuma@chromium.orgedd75742019-09-11 14:52:18 +00002827 stopAllLoaders(ShouldClearProvisionalItem, StopLoadingPolicy::AlwaysStopLoading);
dbates@webkit.org6d862de2017-02-11 02:53:53 +00002828 }
arobendfc56662007-06-21 01:37:24 +00002829
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00002830 InspectorInstrumentation::frameDetachedFromParent(m_frame);
arobendfc56662007-06-21 01:37:24 +00002831
beidson@apple.com24f92a52009-09-03 00:07:51 +00002832 detachViewsAndDocumentLoader();
2833
weinig@apple.comeefc25d2013-11-08 22:42:27 +00002834 m_progressTracker = nullptr;
japhet@chromium.org7879dd72012-08-30 02:58:37 +00002835
darin@apple.comfed4d162013-08-25 02:28:06 +00002836 if (Frame* parent = m_frame.tree().parent()) {
darin@apple.com9ace8012017-01-23 06:24:18 +00002837 parent->loader().closeAndRemoveChild(m_frame);
andersca@apple.comdf550b92013-08-15 22:17:17 +00002838 parent->loader().scheduleCheckCompleted();
darin@apple.combe4d3dd2017-07-30 21:44:01 +00002839 parent->loader().scheduleCheckLoadComplete();
weinigc34c71c2007-03-09 16:05:37 +00002840 } else {
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002841 m_frame.setView(nullptr);
akling@apple.com7f50aae2013-08-22 16:01:31 +00002842 m_frame.willDetachPage();
2843 m_frame.detachFromPage();
ddkilzer3adeb2f2006-12-28 23:33:37 +00002844 }
ggarenc04b2c52006-11-30 21:06:14 +00002845}
beidson@apple.com24f92a52009-09-03 00:07:51 +00002846
2847void FrameLoader::detachViewsAndDocumentLoader()
2848{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002849 m_client->detachedFromParent2();
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002850 setDocumentLoader(nullptr);
youenn@apple.comee96d0f2020-03-18 13:59:23 +00002851 m_client->detachedFromParent3();
beidson@apple.com24f92a52009-09-03 00:07:51 +00002852}
commit-queue@webkit.org53c0a6b2020-04-02 07:43:14 +00002853
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002854ResourceRequestCachePolicy FrameLoader::defaultRequestCachingPolicy(const ResourceRequest& request, FrameLoadType loadType, bool isMainResource)
beidson50c3bd82007-01-03 03:11:18 +00002855{
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002856 if (m_overrideCachePolicyForTesting)
2857 return m_overrideCachePolicyForTesting.value();
antti@apple.com5d0c5402017-03-17 19:52:49 +00002858
2859 if (isMainResource) {
2860 if (isReload(loadType) || request.isConditional())
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002861 return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
antti@apple.com5d0c5402017-03-17 19:52:49 +00002862
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002863 return ResourceRequestCachePolicy::UseProtocolCachePolicy;
antti@apple.com5d0c5402017-03-17 19:52:49 +00002864 }
2865
2866 if (request.isConditional())
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002867 return ResourceRequestCachePolicy::ReloadIgnoringCacheData;
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002868
beidson@apple.com33772ac2020-08-15 00:35:42 +00002869 auto* documentLoader = this->documentLoader();
2870 if (documentLoader && documentLoader->isLoadingInAPISense()) {
antti@apple.com5d0c5402017-03-17 19:52:49 +00002871 // If we inherit cache policy from a main resource, we use the DocumentLoader's
2872 // original request cache policy for two reasons:
2873 // 1. For POST requests, we mutate the cache policy for the main resource,
2874 // but we do not want this to apply to subresources
2875 // 2. Delegates that modify the cache policy using willSendRequest: should
2876 // not affect any other resources. Such changes need to be done
2877 // per request.
beidson@apple.com33772ac2020-08-15 00:35:42 +00002878 ResourceRequestCachePolicy mainDocumentOriginalCachePolicy = documentLoader->originalRequest().cachePolicy();
antti@apple.com5d0c5402017-03-17 19:52:49 +00002879 // Back-forward navigations try to load main resource from cache only to avoid re-submitting form data, and start over (with a warning dialog) if that fails.
2880 // This policy is set on initial request too, but should not be inherited.
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002881 return (mainDocumentOriginalCachePolicy == ResourceRequestCachePolicy::ReturnCacheDataDontLoad) ? ResourceRequestCachePolicy::ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
antti@apple.com5d0c5402017-03-17 19:52:49 +00002882 }
2883
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002884 return ResourceRequestCachePolicy::UseProtocolCachePolicy;
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002885}
2886
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00002887void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, IsMainResource mainResource, FrameLoadType loadType)
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002888{
cdumez@apple.com3aedc032019-01-31 02:23:55 +00002889 // If the request came from a previous process due to process-swap-on-navigation then we should not modify the request.
2890 if (m_currentLoadContinuingState == LoadContinuingState::ContinuingWithRequest)
cdumez@apple.comfdb89712018-06-11 20:52:31 +00002891 return;
2892
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002893 // Don't set the cookie policy URL if it's already been set.
2894 // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00002895 bool isMainResource = mainResource == IsMainResource::Yes;
dbates@webkit.org2dc5b0d2019-02-21 23:54:40 +00002896 bool isMainFrameMainResource = isMainResource && m_frame.isMainFrame();
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002897 if (request.firstPartyForCookies().isEmpty()) {
dbates@webkit.org2dc5b0d2019-02-21 23:54:40 +00002898 if (isMainFrameMainResource)
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002899 request.setFirstPartyForCookies(request.url());
2900 else if (Document* document = m_frame.document())
2901 request.setFirstPartyForCookies(document->firstPartyForCookies());
2902 }
2903
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002904 if (request.isSameSiteUnspecified()) {
2905 auto* initiator = m_frame.document();
2906 if (isMainResource) {
2907 auto* ownerFrame = m_frame.tree().parent();
dbates@webkit.org1e858552018-06-30 02:11:01 +00002908 if (!ownerFrame && m_stateMachine.isDisplayingInitialEmptyDocument())
achristensen@apple.com2ace43d2020-11-05 16:54:48 +00002909 ownerFrame = m_opener.get();
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002910 if (ownerFrame)
2911 initiator = ownerFrame->document();
2912 ASSERT(ownerFrame || m_frame.isMainFrame());
2913 }
2914 addSameSiteInfoToRequestIfNeeded(request, initiator);
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002915 }
dbates@webkit.org2dc5b0d2019-02-21 23:54:40 +00002916 request.setIsTopSite(isMainFrameMainResource);
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002917
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002918 Page* page = frame().page();
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002919 bool hasSpecificCachePolicy = request.cachePolicy() != ResourceRequestCachePolicy::UseProtocolCachePolicy;
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002920
cdumez@apple.coma231c912019-10-16 18:24:25 +00002921 if (page && page->isResourceCachingDisabledByWebInspector()) {
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002922 request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002923 loadType = FrameLoadType::ReloadFromOrigin;
2924 } else if (!hasSpecificCachePolicy)
2925 request.setCachePolicy(defaultRequestCachingPolicy(request, loadType, isMainResource));
ap@apple.com8d5f01b2013-01-07 18:40:55 +00002926
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002927 // The remaining modifications are only necessary for HTTP and HTTPS.
2928 if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
2929 return;
antti@apple.com7c97e2c2015-03-19 05:21:40 +00002930
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00002931 if (!hasSpecificCachePolicy && request.cachePolicy() == ResourceRequestCachePolicy::ReloadIgnoringCacheData) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002932 if (loadType == FrameLoadType::Reload)
commit-queue@webkit.orgf1fbce62020-01-01 11:25:53 +00002933 request.setHTTPHeaderField(HTTPHeaderName::CacheControl, HTTPHeaderValues::maxAge0());
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002934 else if (loadType == FrameLoadType::ReloadFromOrigin) {
commit-queue@webkit.orgf1fbce62020-01-01 11:25:53 +00002935 request.setHTTPHeaderField(HTTPHeaderName::CacheControl, HTTPHeaderValues::noCache());
2936 request.setHTTPHeaderField(HTTPHeaderName::Pragma, HTTPHeaderValues::noCache());
japhet@chromium.org1e313142010-08-31 22:53:31 +00002937 }
2938 }
darin@apple.com0fdefc32016-03-18 07:56:20 +00002939
commit-queue@webkit.org79f5a002016-10-11 10:53:22 +00002940 if (m_overrideResourceLoadPriorityForTesting)
2941 request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
2942
cdumez@apple.com1f985b82020-05-01 23:07:38 +00002943 // Make sure we send the Origin header.
2944 addHTTPOriginIfNeeded(request, String());
2945
commit-queue@webkit.org77e24052020-06-26 01:03:22 +00002946 applyUserAgentIfNeeded(request);
2947
2948 if (isMainResource)
2949 request.setHTTPHeaderField(HTTPHeaderName::Accept, CachedResourceRequest::acceptHeaderValueFromType(CachedResource::Type::MainResource));
2950
ap@apple.com9454f7c2013-06-20 20:06:02 +00002951 // Only set fallback array if it's still empty (later attempts may be incorrect, see bug 117818).
2952 if (request.responseContentDispositionEncodingFallbackArray().isEmpty()) {
2953 // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
akling@apple.com7f50aae2013-08-22 16:01:31 +00002954 request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_frame.document()->encoding(), m_frame.settings().defaultTextEncodingName());
ap@apple.com9454f7c2013-06-20 20:06:02 +00002955 }
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002956}
2957
cdumez@apple.com1f985b82020-05-01 23:07:38 +00002958void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin)
2959{
2960 if (!request.httpOrigin().isEmpty())
2961 return; // Request already has an Origin header.
2962
2963 // Don't send an Origin header for GET or HEAD to avoid privacy issues.
2964 // For example, if an intranet page has a hyperlink to an external web
2965 // site, we don't want to include the Origin of the request because it
2966 // will leak the internal host name. Similar privacy concerns have lead
2967 // to the widespread suppression of the Referer header at the network
2968 // layer.
2969 if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
2970 return;
2971
2972 // FIXME: take referrer-policy into account.
2973 // https://bugs.webkit.org/show_bug.cgi?id=209066
2974
2975 // For non-GET and non-HEAD methods, always send an Origin header so the
2976 // server knows we support this feature.
2977
2978 if (origin.isEmpty()) {
2979 // If we don't know what origin header to attach, we attach the value
2980 // for an empty origin.
2981 request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
2982 return;
2983 }
2984
2985 request.setHTTPOrigin(origin);
2986}
2987
dbates@webkit.org8c917f22018-04-24 07:36:59 +00002988// Implements the "'Same-site' and 'cross-site' Requests" algorithm from <https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site-00#section-2.1>.
2989// The algorithm is ammended to treat URLs that inherit their security origin from their owner (e.g. about:blank)
2990// as same-site. This matches the behavior of Chrome and Firefox.
2991void FrameLoader::addSameSiteInfoToRequestIfNeeded(ResourceRequest& request, const Document* initiator)
2992{
2993 if (!request.isSameSiteUnspecified())
2994 return;
2995 if (!initiator) {
2996 request.setIsSameSite(true);
2997 return;
2998 }
2999 if (SecurityPolicy::shouldInheritSecurityOriginFromOwner(request.url())) {
3000 request.setIsSameSite(true);
3001 return;
3002 }
cdumez@apple.com0b8674fb2019-03-13 19:53:41 +00003003 request.setIsSameSite(areRegistrableDomainsEqual(initiator->siteForCookies(), request.url()));
dbates@webkit.org8c917f22018-04-24 07:36:59 +00003004}
3005
bfulgham@apple.com657c5c72018-05-24 05:23:00 +00003006void FrameLoader::loadPostRequest(FrameLoadRequest&& request, const String& referrer, FrameLoadType loadType, Event* event, RefPtr<FormState>&& formState, CompletionHandler<void()>&& completionHandler)
anderscade5715d2007-01-06 00:55:49 +00003007{
krollin@apple.combdeaed72020-01-08 01:31:20 +00003008 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadPostRequest: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00003009
beidson@apple.combd66a782015-05-29 16:31:49 +00003010 String frameName = request.frameName();
3011 LockHistory lockHistory = request.lockHistory();
3012 AllowNavigationToInvalidURL allowNavigationToInvalidURL = request.allowNavigationToInvalidURL();
3013 NewFrameOpenerPolicy openerPolicy = request.newFrameOpenerPolicy();
3014
3015 const ResourceRequest& inRequest = request.resourceRequest();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003016 const URL& url = inRequest.url();
mrowe@apple.com713db2e2008-07-27 03:49:29 +00003017 const String& contentType = inRequest.httpContentType();
abarth@webkit.orgfb074382008-10-05 19:12:30 +00003018 String origin = inRequest.httpOrigin();
mrowe@apple.com713db2e2008-07-27 03:49:29 +00003019
3020 ResourceRequest workingResourceRequest(url);
anderscade5715d2007-01-06 00:55:49 +00003021
3022 if (!referrer.isEmpty())
mrowe@apple.com713db2e2008-07-27 03:49:29 +00003023 workingResourceRequest.setHTTPReferrer(referrer);
abarth@webkit.orgfb074382008-10-05 19:12:30 +00003024 workingResourceRequest.setHTTPOrigin(origin);
mrowe@apple.com713db2e2008-07-27 03:49:29 +00003025 workingResourceRequest.setHTTPMethod("POST");
youenn.fablet@crf.canon.fr11cc6552016-01-22 14:51:16 +00003026 workingResourceRequest.setHTTPBody(inRequest.httpBody());
mrowe@apple.com713db2e2008-07-27 03:49:29 +00003027 workingResourceRequest.setHTTPContentType(contentType);
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00003028 addExtraFieldsToRequest(workingResourceRequest, IsMainResource::Yes, loadType);
anderscade5715d2007-01-06 00:55:49 +00003029
bfulgham@apple.comb30d7f82016-06-07 15:47:30 +00003030 if (Document* document = m_frame.document())
3031 document->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(workingResourceRequest, ContentSecurityPolicy::InsecureRequestType::Load);
3032
commit-queue@webkit.orgbed33c62020-04-28 20:41:35 +00003033 NavigationAction action { request.requester(), workingResourceRequest, request.initiatedByMainFrame(), loadType, true, event, request.shouldOpenExternalURLsPolicy(), { } };
commit-queue@webkit.org4a7ad282020-04-05 05:09:42 +00003034 action.setLockHistory(lockHistory);
anderscade5715d2007-01-06 00:55:49 +00003035
anderscade5715d2007-01-06 00:55:49 +00003036 if (!frameName.isEmpty()) {
darin@apple.com0f88bda2009-04-02 00:30:50 +00003037 // The search for a target frame is done earlier in the case of form submission.
bfulgham@apple.com657c5c72018-05-24 05:23:00 +00003038 if (auto* targetFrame = formState ? nullptr : findFrameForNavigation(frameName)) {
commit-queue@webkit.orgbed33c62020-04-28 20:41:35 +00003039 targetFrame->loader().loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, WTFMove(completionHandler));
andersca@apple.com096333f2013-11-07 21:37:36 +00003040 return;
darin@chromium.org1e25ab72012-04-02 20:14:07 +00003041 }
andersca@apple.com096333f2013-11-07 21:37:36 +00003042
commit-queue@webkit.org57af63c2020-04-29 10:23:01 +00003043 policyChecker().checkNewWindowPolicy(WTFMove(action), WTFMove(workingResourceRequest), WTFMove(formState), frameName, [this, allowNavigationToInvalidURL, openerPolicy, completionHandler = WTFMove(completionHandler)] (const ResourceRequest& request, WeakPtr<FormState>&& formState, const String& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue) mutable {
bfulgham@apple.com657c5c72018-05-24 05:23:00 +00003044 continueLoadAfterNewWindowPolicy(request, formState.get(), frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
cdumez@apple.comb76757c2018-03-06 22:01:27 +00003045 completionHandler();
andersca@apple.com096333f2013-11-07 21:37:36 +00003046 });
3047 return;
3048 }
3049
3050 // must grab this now, since this load may stop the previous load and clear this flag
3051 bool isRedirect = m_quickRedirectComing;
commit-queue@webkit.orgbed33c62020-04-28 20:41:35 +00003052 loadWithNavigationAction(workingResourceRequest, WTFMove(action), loadType, WTFMove(formState), allowNavigationToInvalidURL, [this, isRedirect, protectedFrame = makeRef(m_frame), completionHandler = WTFMove(completionHandler)] () mutable {
cdumez@apple.comb76757c2018-03-06 22:01:27 +00003053 if (isRedirect) {
3054 m_quickRedirectComing = false;
3055 if (m_provisionalDocumentLoader)
3056 m_provisionalDocumentLoader->setIsClientRedirect(true);
3057 else if (m_policyDocumentLoader)
3058 m_policyDocumentLoader->setIsClientRedirect(true);
3059 }
3060 completionHandler();
3061 });
anderscade5715d2007-01-06 00:55:49 +00003062}
3063
youenn@apple.comb9709cc2018-04-16 21:50:26 +00003064unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, ClientCredentialPolicy clientCredentialPolicy, const FetchOptions& options, const HTTPHeaderMap& originalRequestHeaders, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
anderscade5715d2007-01-06 00:55:49 +00003065{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003066 ASSERT(m_frame.document());
3067 String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), request.url(), outgoingReferrer());
anderscade5715d2007-01-06 00:55:49 +00003068
3069 ResourceRequest initialRequest = request;
3070 initialRequest.setTimeoutInterval(10);
3071
anderscade5715d2007-01-06 00:55:49 +00003072 if (!referrer.isEmpty())
3073 initialRequest.setHTTPReferrer(referrer);
cdumez@apple.com1f985b82020-05-01 23:07:38 +00003074 addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
darine0cef432007-07-10 19:21:23 +00003075
darin@apple.com0e83ab12013-09-28 17:19:04 +00003076 initialRequest.setFirstPartyForCookies(m_frame.mainFrame().loader().documentLoader()->request().url());
japhet@chromium.org92a952b2010-07-12 18:14:17 +00003077
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00003078 addExtraFieldsToRequest(initialRequest, IsMainResource::No);
darine0cef432007-07-10 19:21:23 +00003079
commit-queue@webkit.org84a72092020-04-23 20:37:54 +00003080 applyUserAgentIfNeeded(initialRequest);
3081
anderscaec429f52007-01-13 01:44:24 +00003082 unsigned long identifier = 0;
anderscade5715d2007-01-06 00:55:49 +00003083 ResourceRequest newRequest(initialRequest);
3084 requestFromDelegate(newRequest, identifier, error);
3085
beidson@apple.come3ea01d2015-07-02 18:33:23 +00003086#if ENABLE(CONTENT_EXTENSIONS)
3087 if (error.isNull()) {
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +00003088 if (auto* page = m_frame.page()) {
commit-queue@webkit.org3d339842016-08-04 18:07:45 +00003089 if (m_documentLoader) {
achristensen@apple.comb80d3422019-04-26 17:03:15 +00003090 auto results = page->userContentProvider().processContentRuleListsForLoad(newRequest.url(), ContentExtensions::ResourceType::Raw, *m_documentLoader);
achristensen@apple.comd3edc2a2019-03-21 20:23:46 +00003091 bool blockedLoad = results.summary.blockedLoad;
3092 ContentExtensions::applyResultsToRequest(WTFMove(results), page, newRequest);
3093 if (blockedLoad) {
commit-queue@webkit.org3d339842016-08-04 18:07:45 +00003094 newRequest = { };
3095 error = ResourceError(errorDomainWebKitInternal, 0, initialRequest.url(), emptyString());
3096 response = { };
3097 data = nullptr;
3098 }
beidson@apple.come3ea01d2015-07-02 18:33:23 +00003099 }
3100 }
beidson@apple.come3ea01d2015-07-02 18:33:23 +00003101 }
3102#endif
3103
bfulgham@apple.comb30d7f82016-06-07 15:47:30 +00003104 m_frame.document()->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(newRequest, ContentSecurityPolicy::InsecureRequestType::Load);
3105
anderscade5715d2007-01-06 00:55:49 +00003106 if (error.isNull()) {
3107 ASSERT(!newRequest.isNull());
youenn.fablet@crf.canon.fr0aef67f2015-04-29 08:18:10 +00003108
darin@apple.comc04189e2017-01-18 05:17:17 +00003109 if (!documentLoader()->applicationCacheHost().maybeLoadSynchronously(newRequest, error, response, data)) {
youenn.fablet@crf.canon.fr0aef67f2015-04-29 08:18:10 +00003110 Vector<char> buffer;
youenn@apple.comb9709cc2018-04-16 21:50:26 +00003111 platformStrategies()->loaderStrategy()->loadResourceSynchronously(*this, identifier, newRequest, clientCredentialPolicy, options, originalRequestHeaders, error, response, buffer);
commit-queue@webkit.org08f38b92017-04-12 09:25:04 +00003112 data = SharedBuffer::create(WTFMove(buffer));
darin@apple.comc04189e2017-01-18 05:17:17 +00003113 documentLoader()->applicationCacheHost().maybeLoadFallbackSynchronously(newRequest, error, response, data);
wilander@apple.coma4d606a2019-11-19 20:35:21 +00003114 ResourceLoadObserver::shared().logSubresourceLoading(&m_frame, newRequest, response,
3115 (isScriptLikeDestination(options.destination) ? ResourceLoadObserver::FetchDestinationIsScriptLike::Yes : ResourceLoadObserver::FetchDestinationIsScriptLike::No));
ap@webkit.orgfb96f8a2009-01-02 09:25:02 +00003116 }
anderscade5715d2007-01-06 00:55:49 +00003117 }
youenn.fablet@crf.canon.fr0aef67f2015-04-29 08:18:10 +00003118 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, data ? data->data() : nullptr, data ? data->size() : 0, -1, error);
kmccullough@apple.com2a4950c2008-03-28 23:28:56 +00003119 return identifier;
anderscade5715d2007-01-06 00:55:49 +00003120}
3121
anderscade5715d2007-01-06 00:55:49 +00003122const ResourceRequest& FrameLoader::originalRequest() const
3123{
3124 return activeDocumentLoader()->originalRequestCopy();
3125}
3126
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00003127void FrameLoader::receivedMainResourceError(const ResourceError& error)
anderscade5715d2007-01-06 00:55:49 +00003128{
3129 // Retain because the stop may release the last reference to it.
akling@apple.comf8515982013-09-02 18:50:01 +00003130 Ref<Frame> protect(m_frame);
anderscade5715d2007-01-06 00:55:49 +00003131
3132 RefPtr<DocumentLoader> loader = activeDocumentLoader();
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00003133 // FIXME: Don't want to do this if an entirely new load is going, so should check
3134 // that both data sources on the frame are either this or nil.
3135 stop();
commit-queue@webkit.org15deb6e2020-06-08 09:04:33 +00003136 if (m_client->shouldFallBack(error)) {
3137 HTMLFrameOwnerElement* owner = m_frame.ownerElement();
3138 if (is<HTMLObjectElement>(owner))
3139 downcast<HTMLObjectElement>(*owner).renderFallbackContent();
3140 }
abarth@webkit.org1c893f42009-10-10 02:27:21 +00003141
lars8bf288d2007-10-04 08:45:12 +00003142 if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
darin@apple.com4cd1b242009-03-27 23:37:46 +00003143 if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003144 m_submittedFormURL = URL();
anttiac25cb42007-03-02 07:59:15 +00003145
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003146 // We might have made a back/forward cache item, but now we're bailing out due to an error before we ever
anderscade5715d2007-01-06 00:55:49 +00003147 // transitioned to the new page (before WebFrameState == commit). The goal here is to restore any state
3148 // so that the existing view (that wenever got far enough to replace) can continue being used.
akling@apple.com672cb852013-08-22 20:27:27 +00003149 history().invalidateCurrentItemCachedPage();
anderscade5715d2007-01-06 00:55:49 +00003150
3151 // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
3152 // status has changed, if there was a redirect. The frame load delegate may have saved some state about
3153 // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
3154 // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
3155 // has ended.
3156 if (m_sentRedirectNotification)
achristensen@apple.com6fddc912018-10-18 21:16:52 +00003157 clientRedirectCancelledOrFinished(NewLoadInProgress::No);
anderscade5715d2007-01-06 00:55:49 +00003158 }
abarth@webkit.org1c893f42009-10-10 02:27:21 +00003159
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00003160 checkCompleted();
akling@apple.com7f50aae2013-08-22 16:01:31 +00003161 if (m_frame.page())
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00003162 checkLoadComplete();
anderscade5715d2007-01-06 00:55:49 +00003163}
3164
anderscade5715d2007-01-06 00:55:49 +00003165void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
3166{
anderscade5715d2007-01-06 00:55:49 +00003167 m_quickRedirectComing = false;
darin4e5519d2007-01-22 02:46:06 +00003168
3169 if (!shouldContinue)
3170 return;
3171
bfulgham@apple.com98845d92016-05-17 01:09:27 +00003172 // Calling stopLoading() on the provisional document loader can cause the underlying
3173 // frame to be deallocated.
3174 Ref<Frame> protectedFrame(m_frame);
3175
mihaip@chromium.orgd5123ba2011-09-16 02:16:46 +00003176 // If we have a provisional request for a different document, a fragment scroll should cancel it.
3177 if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
3178 m_provisionalDocumentLoader->stopLoading();
krollin@apple.combdeaed72020-01-08 01:31:20 +00003179 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueFragmentScrollAfterNavigationPolicy: Clearing provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00003180 setProvisionalDocumentLoader(nullptr);
mihaip@chromium.orgd5123ba2011-09-16 02:16:46 +00003181 }
3182
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003183 bool isRedirect = m_quickRedirectComing || policyChecker().loadType() == FrameLoadType::RedirectWithLockedBackForwardList;
beidson@apple.com08c61752009-12-03 19:04:40 +00003184 loadInSameDocument(request.url(), 0, !isRedirect);
anderscade5715d2007-01-06 00:55:49 +00003185}
3186
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003187bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const URL& url)
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00003188{
yael.aharon@nokia.com79f69052010-12-30 19:31:00 +00003189 // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00003190 // currently displaying a frameset, or if the URL does not have a fragment.
3191 // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
3192
3193 // FIXME: What about load types other than Standard and Reload?
3194
darin@apple.com048cc3a2016-01-22 17:17:04 +00003195 return (!isFormSubmission || equalLettersIgnoringASCIICase(httpMethod, "get"))
antti@apple.com5d0c5402017-03-17 19:52:49 +00003196 && !isReload(loadType)
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003197 && loadType != FrameLoadType::Same
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003198 && m_frame.document()->backForwardCacheState() != Document::InBackForwardCache
akling@apple.com7f50aae2013-08-22 16:01:31 +00003199 && !shouldReload(m_frame.document()->url(), url)
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00003200 // We don't want to just scroll if a link from within a
3201 // frameset is trying to reload the frameset into _top.
akling@apple.com7f50aae2013-08-22 16:01:31 +00003202 && !m_frame.document()->isFrameSet();
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00003203}
3204
simon.fraser@apple.comc79e4862017-03-08 20:01:15 +00003205static bool itemAllowsScrollRestoration(HistoryItem* historyItem)
3206{
simon.fraser@apple.com804555f2017-11-29 20:41:47 +00003207 return !historyItem || historyItem->shouldRestoreScrollPosition();
simon.fraser@apple.comc79e4862017-03-08 20:01:15 +00003208}
3209
3210static bool isSameDocumentReload(bool isNewNavigation, FrameLoadType loadType)
3211{
3212 return !isNewNavigation && !isBackForwardLoadType(loadType);
3213}
3214
3215void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url, bool isNewNavigation)
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00003216{
rniwa@webkit.org892a3762019-11-22 05:09:36 +00003217 auto view = makeRefPtr(m_frame.view());
3218 auto document = makeRefPtr(m_frame.document());
3219 if (!view || !document)
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00003220 return;
3221
rniwa@webkit.org892a3762019-11-22 05:09:36 +00003222 if (isSameDocumentReload(isNewNavigation, m_loadType) || itemAllowsScrollRestoration(history().currentItem())) {
3223 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#try-to-scroll-to-the-fragment
3224 if (!document->haveStylesheetsLoaded())
3225 document->setGotoAnchorNeededAfterStylesheetsLoad(true);
3226 else
3227 view->scrollToFragment(url);
3228 }
3229
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00003230}
3231
beidson@apple.com7617ce72010-05-13 20:31:46 +00003232bool FrameLoader::shouldClose()
3233{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003234 Page* page = m_frame.page();
akling@apple.combd774812013-05-17 00:03:01 +00003235 if (!page)
3236 return true;
3237 if (!page->chrome().canRunBeforeUnloadConfirmPanel())
beidson@apple.com7617ce72010-05-13 20:31:46 +00003238 return true;
3239
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00003240 // Store all references to each subframe in advance since beforeunload's event handler may modify frame
akling@apple.com72c1c362013-09-06 01:34:05 +00003241 Vector<Ref<Frame>, 16> targetFrames;
3242 targetFrames.append(m_frame);
darin@apple.comfed4d162013-08-25 02:28:06 +00003243 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
akling@apple.com72c1c362013-09-06 01:34:05 +00003244 targetFrames.append(*child);
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00003245
3246 bool shouldClose = false;
3247 {
rniwa@webkit.orgf694bd62017-06-30 19:32:41 +00003248 NavigationDisabler navigationDisabler(&m_frame);
cdumez@apple.come4df29d2018-09-26 19:29:54 +00003249 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00003250 size_t i;
3251
3252 for (i = 0; i < targetFrames.size(); i++) {
darin@apple.comfed4d162013-08-25 02:28:06 +00003253 if (!targetFrames[i]->tree().isDescendantOf(&m_frame))
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00003254 continue;
ggaren@apple.com7a176e12015-11-12 01:48:27 +00003255 if (!targetFrames[i]->loader().dispatchBeforeUnloadEvent(page->chrome(), this))
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00003256 break;
3257 }
3258
3259 if (i == targetFrames.size())
3260 shouldClose = true;
3261 }
3262
aestes@apple.comc7f17612011-08-12 19:56:56 +00003263 if (!shouldClose)
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003264 m_submittedFormURL = URL();
aestes@apple.comc7f17612011-08-12 19:56:56 +00003265
beidson@apple.com1390a812013-07-20 06:43:51 +00003266 m_currentNavigationHasShownBeforeUnloadConfirmPanel = false;
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00003267 return shouldClose;
3268}
3269
ggaren@apple.com7a176e12015-11-12 01:48:27 +00003270void FrameLoader::dispatchUnloadEvents(UnloadEventPolicy unloadEventPolicy)
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003271{
3272 if (!m_frame.document())
3273 return;
3274
ajuma@chromium.orgedd75742019-09-11 14:52:18 +00003275 if (m_pageDismissalEventBeingDispatched != PageDismissalType::None)
3276 return;
3277
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003278 // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
3279 ForbidPromptsScope forbidPrompts(m_frame.page());
cdumez@apple.comfc8fdf32019-12-06 21:05:12 +00003280 ForbidSynchronousLoadsScope forbidSynchronousLoads(m_frame.page());
cdumez@apple.com8b478c62016-01-23 01:04:59 +00003281 IgnoreOpensDuringUnloadCountIncrementer ignoreOpensDuringUnloadCountIncrementer(m_frame.document());
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003282
3283 if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
3284 auto* currentFocusedElement = m_frame.document()->focusedElement();
3285 if (is<HTMLInputElement>(currentFocusedElement))
3286 downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
3287 if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
3288 if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
3289 m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003290 m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->backForwardCacheState() == Document::AboutToEnterBackForwardCache), m_frame.document());
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003291 }
3292
cdumez@apple.com19a0fdc2020-09-26 00:50:00 +00003293 // This takes care of firing the visibilitychange event and making sure the document is reported as hidden.
3294 m_frame.document()->setVisibilityHiddenDueToDismissal(true);
cdumez@apple.com3bd17f72020-09-25 21:29:46 +00003295
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003296 if (m_frame.document()->backForwardCacheState() == Document::NotInBackForwardCache) {
rniwa@webkit.org6c403742018-08-17 21:24:40 +00003297 Ref<Event> unloadEvent(Event::create(eventNames().unloadEvent, Event::CanBubble::No, Event::IsCancelable::No));
commit-queue@webkit.org3eeac492016-08-12 22:53:27 +00003298 // The DocumentLoader (and thus its LoadTiming) might get destroyed
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003299 // while dispatching the event, so protect it to prevent writing the end
3300 // time into freed memory.
3301 RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
3302 m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
commit-queue@webkit.org3eeac492016-08-12 22:53:27 +00003303 if (documentLoader && documentLoader->timing().startTime() && !documentLoader->timing().unloadEventStart() && !documentLoader->timing().unloadEventEnd()) {
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003304 auto& timing = documentLoader->timing();
3305 timing.markUnloadEventStart();
3306 m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
3307 timing.markUnloadEventEnd();
3308 } else
3309 m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
3310 }
3311 }
3312 m_pageDismissalEventBeingDispatched = PageDismissalType::None;
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003313 m_wasUnloadEventEmitted = true;
3314 }
3315
3316 // Dispatching the unload event could have made m_frame.document() null.
3317 if (!m_frame.document())
3318 return;
3319
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003320 if (m_frame.document()->backForwardCacheState() != Document::NotInBackForwardCache)
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003321 return;
3322
3323 // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
3324 bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
3325 && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
3326
3327 if (!keepEventListeners)
3328 m_frame.document()->removeAllEventListeners();
3329}
3330
cdumez@apple.com6473cc42017-03-22 21:14:23 +00003331static bool shouldAskForNavigationConfirmation(Document& document, const BeforeUnloadEvent& event)
cdumez@apple.com60045462017-02-20 06:36:04 +00003332{
fred.wang@free.frd6e82742017-08-25 17:28:53 +00003333 // Confirmation dialog should not be displayed when the allow-modals flag is not set.
3334 if (document.isSandboxed(SandboxModals))
3335 return false;
3336
cdumez@apple.com72d8e4b2017-04-17 00:56:47 +00003337 bool userDidInteractWithPage = document.topDocument().userDidInteractWithPage();
cdumez@apple.com60045462017-02-20 06:36:04 +00003338 // Web pages can request we ask for confirmation before navigating by:
3339 // - Cancelling the BeforeUnloadEvent (modern way)
3340 // - Setting the returnValue attribute on the BeforeUnloadEvent to a non-empty string.
3341 // - Returning a non-empty string from the event handler, which is then set as returnValue
3342 // attribute on the BeforeUnloadEvent.
cdumez@apple.com6473cc42017-03-22 21:14:23 +00003343 return userDidInteractWithPage && (event.defaultPrevented() || !event.returnValue().isEmpty());
cdumez@apple.com60045462017-02-20 06:36:04 +00003344}
3345
ggaren@apple.com7a176e12015-11-12 01:48:27 +00003346bool FrameLoader::dispatchBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00003347{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003348 DOMWindow* domWindow = m_frame.document()->domWindow();
beidson@apple.com7617ce72010-05-13 20:31:46 +00003349 if (!domWindow)
3350 return true;
3351
akling@apple.com7f50aae2013-08-22 16:01:31 +00003352 RefPtr<Document> document = m_frame.document();
cdumez@apple.comf9780832015-01-27 00:26:21 +00003353 if (!document->bodyOrFrameset())
beidson@apple.com7617ce72010-05-13 20:31:46 +00003354 return true;
beidson@apple.com1390a812013-07-20 06:43:51 +00003355
cdumez@apple.com32216e42015-11-12 07:28:57 +00003356 Ref<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
beidson@apple.com1390a812013-07-20 06:43:51 +00003357
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003358 {
ajuma@chromium.orgedd75742019-09-11 14:52:18 +00003359 SetForScope<PageDismissalType> change(m_pageDismissalEventBeingDispatched, PageDismissalType::BeforeUnload);
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003360 ForbidPromptsScope forbidPrompts(m_frame.page());
cdumez@apple.comfc8fdf32019-12-06 21:05:12 +00003361 ForbidSynchronousLoadsScope forbidSynchronousLoads(m_frame.page());
cdumez@apple.com32216e42015-11-12 07:28:57 +00003362 domWindow->dispatchEvent(beforeUnloadEvent, domWindow->document());
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00003363 }
beidson@apple.com1390a812013-07-20 06:43:51 +00003364
beidson@apple.com7617ce72010-05-13 20:31:46 +00003365 if (!beforeUnloadEvent->defaultPrevented())
akling@apple.come8090dd2016-08-31 16:32:44 +00003366 document->defaultEventHandler(beforeUnloadEvent.get());
cdumez@apple.com60045462017-02-20 06:36:04 +00003367
cdumez@apple.com6473cc42017-03-22 21:14:23 +00003368 if (!shouldAskForNavigationConfirmation(*document, beforeUnloadEvent))
beidson@apple.com7617ce72010-05-13 20:31:46 +00003369 return true;
3370
beidson@apple.com1390a812013-07-20 06:43:51 +00003371 // If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
3372 // this frame is not allowed to cause another one to be shown.
3373 if (frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel) {
utatane.tea@gmail.com84077632018-06-23 08:39:34 +00003374 document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Blocked attempt to show multiple beforeunload confirmation dialogs for the same navigation."_s);
beidson@apple.com1390a812013-07-20 06:43:51 +00003375 return true;
3376 }
3377
3378 // We should only display the beforeunload dialog for an iframe if its SecurityOrigin matches all
3379 // ancestor frame SecurityOrigins up through the navigating FrameLoader.
3380 if (frameLoaderBeingNavigated != this) {
darin@apple.comfed4d162013-08-25 02:28:06 +00003381 Frame* parentFrame = m_frame.tree().parent();
beidson@apple.com1390a812013-07-20 06:43:51 +00003382 while (parentFrame) {
3383 Document* parentDocument = parentFrame->document();
3384 if (!parentDocument)
3385 return true;
akling@apple.com6be0e972017-01-18 19:35:49 +00003386 if (!m_frame.document() || !m_frame.document()->securityOrigin().canAccess(parentDocument->securityOrigin())) {
utatane.tea@gmail.com84077632018-06-23 08:39:34 +00003387 document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Blocked attempt to show beforeunload confirmation dialog on behalf of a frame with different security origin. Protocols, domains, and ports must match."_s);
beidson@apple.com1390a812013-07-20 06:43:51 +00003388 return true;
3389 }
3390
andersca@apple.comdf550b92013-08-15 22:17:17 +00003391 if (&parentFrame->loader() == frameLoaderBeingNavigated)
beidson@apple.com1390a812013-07-20 06:43:51 +00003392 break;
3393
darin@apple.comfed4d162013-08-25 02:28:06 +00003394 parentFrame = parentFrame->tree().parent();
beidson@apple.com1390a812013-07-20 06:43:51 +00003395 }
3396
3397 // The navigatingFrameLoader should always be in our ancestory.
3398 ASSERT(parentFrame);
andersca@apple.comdf550b92013-08-15 22:17:17 +00003399 ASSERT(&parentFrame->loader() == frameLoaderBeingNavigated);
beidson@apple.com1390a812013-07-20 06:43:51 +00003400 }
3401
3402 frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel = true;
3403
ch.dumez@sisa.samsung.com231386f2013-09-09 18:40:04 +00003404 String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->returnValue());
darin@apple.com9ace8012017-01-23 06:24:18 +00003405 return chrome.runBeforeUnloadConfirmPanel(text, m_frame);
beidson@apple.com7617ce72010-05-13 20:31:46 +00003406}
3407
cdumez@apple.com2e665842019-02-01 22:52:58 +00003408void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, FormState* formState, NavigationPolicyDecision navigationPolicyDecision, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
anderscade5715d2007-01-06 00:55:49 +00003409{
3410 // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
3411 // nil policyDataSource because loading the alternate page will have passed
3412 // through this method already, nested; otherwise, policyDataSource should still be set.
3413 ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
3414
akling@apple.com672cb852013-08-22 20:27:27 +00003415 bool isTargetItem = history().provisionalItem() ? history().provisionalItem()->isTargetItem() : false;
anderscade5715d2007-01-06 00:55:49 +00003416
aestes@apple.com47ac5e12014-08-18 17:48:48 +00003417 bool urlIsDisallowed = allowNavigationToInvalidURL == AllowNavigationToInvalidURL::No && !request.url().isValid();
cdumez@apple.com2e665842019-02-01 22:52:58 +00003418 bool canContinue = navigationPolicyDecision == NavigationPolicyDecision::ContinueLoad && shouldClose() && !urlIsDisallowed;
anderscade5715d2007-01-06 00:55:49 +00003419
3420 if (!canContinue) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00003421 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueLoadAfterNavigationPolicy: can't continue loading frame due to the following reasons ("
krollin@apple.come1810b62018-12-20 19:23:20 +00003422 "allowNavigationToInvalidURL = %d, "
3423 "requestURLIsValid = %d, "
cdumez@apple.com2e665842019-02-01 22:52:58 +00003424 "navigationPolicyDecision = %d)",
krollin@apple.come1810b62018-12-20 19:23:20 +00003425 static_cast<int>(allowNavigationToInvalidURL),
3426 request.url().isValid(),
cdumez@apple.com2e665842019-02-01 22:52:58 +00003427 static_cast<int>(navigationPolicyDecision));
krollin@apple.come1810b62018-12-20 19:23:20 +00003428
anderscade5715d2007-01-06 00:55:49 +00003429 // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we
3430 // need to report that the client redirect was cancelled.
aestes@apple.com47ac5e12014-08-18 17:48:48 +00003431 // FIXME: The client should be told about ignored non-quick redirects, too.
anderscade5715d2007-01-06 00:55:49 +00003432 if (m_quickRedirectComing)
achristensen@apple.com6fddc912018-10-18 21:16:52 +00003433 clientRedirectCancelledOrFinished(NewLoadInProgress::No);
anderscade5715d2007-01-06 00:55:49 +00003434
cdumez@apple.com2e665842019-02-01 22:52:58 +00003435 if (navigationPolicyDecision == NavigationPolicyDecision::StopAllLoads) {
3436 stopAllLoaders();
3437 m_checkTimer.stop();
3438 }
3439
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00003440 setPolicyDocumentLoader(nullptr);
cdumez@apple.comd6531852018-03-06 03:13:32 +00003441 checkCompleted();
cdumez@apple.com2e665842019-02-01 22:52:58 +00003442
3443 if (navigationPolicyDecision != NavigationPolicyDecision::StopAllLoads)
3444 checkLoadComplete();
anderscade5715d2007-01-06 00:55:49 +00003445
3446 // If the navigation request came from the back/forward menu, and we punt on it, we have the
simon.fraser@apple.comc79e4862017-03-08 20:01:15 +00003447 // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
anderscade5715d2007-01-06 00:55:49 +00003448 // we only do this when punting a navigation for the target frame or top-level frame.
darin@apple.com0e83ab12013-09-28 17:19:04 +00003449 if ((isTargetItem || m_frame.isMainFrame()) && isBackForwardLoadType(policyChecker().loadType())) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00003450 if (Page* page = m_frame.page()) {
achristensen@apple.comebfea932018-10-15 21:45:55 +00003451 if (HistoryItem* resetItem = m_frame.mainFrame().loader().history().currentItem())
achristensen@apple.com3a889f12018-10-16 15:58:10 +00003452 page->backForward().setCurrentItem(*resetItem);
darine0cef432007-07-10 19:21:23 +00003453 }
andersca@apple.comb85d6742011-03-04 03:21:07 +00003454 }
anderscade5715d2007-01-06 00:55:49 +00003455 return;
3456 }
3457
akling@apple.com24f4d6c2013-09-08 08:17:10 +00003458 FrameLoadType type = policyChecker().loadType();
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00003459 // A new navigation is in progress, so don't clear the history's provisional item.
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +00003460 stopAllLoaders(ShouldNotClearProvisionalItem);
beidson@apple.comc90a4422008-10-09 20:43:24 +00003461
3462 // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3463 // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
krollin@apple.come1810b62018-12-20 19:23:20 +00003464 if (!m_frame.page()) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00003465 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueLoadAfterNavigationPolicy: can't continue loading frame because it became defunct");
beidson@apple.comc90a4422008-10-09 20:43:24 +00003466 return;
krollin@apple.come1810b62018-12-20 19:23:20 +00003467 }
timothy@apple.com8f207342009-04-11 05:31:05 +00003468
anderscade5715d2007-01-06 00:55:49 +00003469 setProvisionalDocumentLoader(m_policyDocumentLoader.get());
krollin@apple.combdeaed72020-01-08 01:31:20 +00003470 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueLoadAfterNavigationPolicy: Setting provisional document loader (m_provisionalDocumentLoader=%p)", m_provisionalDocumentLoader.get());
anderscade5715d2007-01-06 00:55:49 +00003471 m_loadType = type;
3472 setState(FrameStateProvisional);
3473
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00003474 setPolicyDocumentLoader(nullptr);
anderscade5715d2007-01-06 00:55:49 +00003475
cdumez@apple.com25743772015-08-17 22:57:27 +00003476 if (isBackForwardLoadType(type)) {
cdumez@apple.com10d0f252016-04-23 21:33:49 +00003477 auto& diagnosticLoggingClient = m_frame.page()->diagnosticLoggingClient();
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003478 if (history().provisionalItem() && history().provisionalItem()->isInBackForwardCache()) {
3479 diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::backForwardCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultPass, ShouldSample::Yes);
cdumez@apple.com25743772015-08-17 22:57:27 +00003480 loadProvisionalItemFromCachedPage();
krollin@apple.combdeaed72020-01-08 01:31:20 +00003481 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueLoadAfterNavigationPolicy: can't continue loading frame because it will be loaded from cache");
cdumez@apple.com25743772015-08-17 22:57:27 +00003482 return;
3483 }
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003484 diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::backForwardCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultFail, ShouldSample::Yes);
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003485 }
anderscade5715d2007-01-06 00:55:49 +00003486
cdumez@apple.coma0010ff2018-12-13 23:17:44 +00003487 CompletionHandler<void()> completionHandler = [this, protectedFrame = makeRef(m_frame)] () mutable {
krollin@apple.come1810b62018-12-20 19:23:20 +00003488 if (!m_provisionalDocumentLoader) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00003489 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueLoadAfterNavigationPolicy (completionHandler): Frame load canceled - no provisional document loader before prepareForLoadStart");
achristensen@apple.comb2d9e112017-09-25 19:18:50 +00003490 return;
krollin@apple.come1810b62018-12-20 19:23:20 +00003491 }
achristensen@apple.comb2d9e112017-09-25 19:18:50 +00003492
achristensen@apple.comc41ad692019-01-31 21:23:44 +00003493 prepareForLoadStart();
beidson@apple.com02622332018-04-13 18:04:22 +00003494
achristensen@apple.comc41ad692019-01-31 21:23:44 +00003495 // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
3496 // so we need to null check it again.
3497 if (!m_provisionalDocumentLoader) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00003498 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueLoadAfterNavigationPolicy (completionHandler): Frame load canceled - no provisional document loader after prepareForLoadStart");
achristensen@apple.comc41ad692019-01-31 21:23:44 +00003499 return;
3500 }
3501
3502 DocumentLoader* activeDocLoader = activeDocumentLoader();
3503 if (activeDocLoader && activeDocLoader->isLoadingMainResource()) {
krollin@apple.combdeaed72020-01-08 01:31:20 +00003504 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "continueLoadAfterNavigationPolicy (completionHandler): Main frame already being loaded");
achristensen@apple.comc41ad692019-01-31 21:23:44 +00003505 return;
3506 }
3507
3508 m_loadingFromCachedPage = false;
beidson@apple.com02622332018-04-13 18:04:22 +00003509
achristensen@apple.comc41ad692019-01-31 21:23:44 +00003510 m_provisionalDocumentLoader->startLoadingMainResource();
achristensen@apple.comb2d9e112017-09-25 19:18:50 +00003511 };
3512
andersca@apple.com61e33322013-10-05 04:52:04 +00003513 if (!formState) {
achristensen@apple.comb2d9e112017-09-25 19:18:50 +00003514 completionHandler();
andersca@apple.com61e33322013-10-05 04:52:04 +00003515 return;
3516 }
3517
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003518 m_client->dispatchWillSubmitForm(*formState, WTFMove(completionHandler));
anderscade5715d2007-01-06 00:55:49 +00003519}
3520
anderscade5715d2007-01-06 00:55:49 +00003521void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
commit-queue@webkit.org57af63c2020-04-29 10:23:01 +00003522 FormState* formState, const String& frameName, const NavigationAction& action, ShouldContinuePolicyCheck shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NewFrameOpenerPolicy openerPolicy)
anderscade5715d2007-01-06 00:55:49 +00003523{
commit-queue@webkit.org57af63c2020-04-29 10:23:01 +00003524 if (shouldContinue != ShouldContinuePolicyCheck::Yes)
anderscade5715d2007-01-06 00:55:49 +00003525 return;
3526
akling@apple.com55cde012013-10-05 00:35:12 +00003527 Ref<Frame> frame(m_frame);
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003528 RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(action);
anderscade5715d2007-01-06 00:55:49 +00003529 if (!mainFrame)
3530 return;
3531
commit-queue@webkit.org04df8422017-06-09 17:59:18 +00003532 SandboxFlags sandboxFlags = frame->loader().effectiveSandboxFlags();
3533 if (sandboxFlags & SandboxPropagatesToAuxiliaryBrowsingContexts)
3534 mainFrame->loader().forceSandboxFlags(sandboxFlags);
wilander@apple.com2d7ea242016-08-08 21:43:36 +00003535
cdumez@apple.comeec032f2017-04-05 13:36:47 +00003536 if (!equalIgnoringASCIICase(frameName, "_blank"))
darin@apple.comfed4d162013-08-25 02:28:06 +00003537 mainFrame->tree().setName(frameName);
kmccullo1f901212007-05-16 20:57:47 +00003538
eric@webkit.org5aee6762009-10-06 18:20:33 +00003539 mainFrame->page()->setOpenedByDOM();
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003540 mainFrame->loader().m_client->dispatchShow();
ap@apple.coma383f252015-02-14 18:16:00 +00003541 if (openerPolicy == NewFrameOpenerPolicy::Allow) {
cdumez@apple.com78141732014-11-04 23:00:48 +00003542 mainFrame->loader().setOpener(frame.ptr());
jochen@chromium.org235ee972012-05-09 22:13:12 +00003543 mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy());
3544 }
beidson@apple.com87dc6312015-06-02 18:43:13 +00003545
cdumez@apple.com548d7bb2018-10-09 18:25:29 +00003546 NavigationAction newAction { *frame->document(), request, InitiatedByMainFrame::Unknown, NavigationType::Other, action.shouldOpenExternalURLsPolicy(), nullptr, action.downloadAttribute() };
commit-queue@webkit.org4a7ad282020-04-05 05:09:42 +00003547 mainFrame->loader().loadWithNavigationAction(request, WTFMove(newAction), FrameLoadType::Standard, formState, allowNavigationToInvalidURL);
anderscade5715d2007-01-06 00:55:49 +00003548}
3549
anderscaec429f52007-01-13 01:44:24 +00003550void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
anderscade5715d2007-01-06 00:55:49 +00003551{
3552 ASSERT(!request.isNull());
3553
darine0cef432007-07-10 19:21:23 +00003554 identifier = 0;
akling@apple.com7f50aae2013-08-22 16:01:31 +00003555 if (Page* page = m_frame.page()) {
akling@apple.comeb67e0a2013-08-19 08:24:08 +00003556 identifier = page->progress().createUniqueIdentifier();
akling@apple.com654fd9a2013-10-06 21:07:29 +00003557 notifier().assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
darine0cef432007-07-10 19:21:23 +00003558 }
anderscaec429f52007-01-13 01:44:24 +00003559
anderscade5715d2007-01-06 00:55:49 +00003560 ResourceRequest newRequest(request);
akling@apple.com654fd9a2013-10-06 21:07:29 +00003561 notifier().dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
anderscade5715d2007-01-06 00:55:49 +00003562
3563 if (newRequest.isNull())
weinig@apple.com87a569c2008-05-18 01:21:20 +00003564 error = cancelledError(request);
anderscade5715d2007-01-06 00:55:49 +00003565 else
3566 error = ResourceError();
3567
3568 request = newRequest;
3569}
3570
cdumez@apple.comd038ecf2017-08-15 21:15:09 +00003571void FrameLoader::loadedResourceFromMemoryCache(CachedResource& resource, ResourceRequest& newRequest, ResourceError& error)
anderscade5715d2007-01-06 00:55:49 +00003572{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003573 Page* page = m_frame.page();
darin@apple.com837a78c2009-01-07 15:40:24 +00003574 if (!page)
anderscade5715d2007-01-06 00:55:49 +00003575 return;
3576
commit-queue@webkit.org39359f02020-04-25 21:28:45 +00003577 if (!resource.shouldSendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource.url().string()))
darin@apple.com837a78c2009-01-07 15:40:24 +00003578 return;
3579
japhet@chromium.org3e317182013-01-29 20:06:19 +00003580 // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00003581 if (resource.type() == CachedResource::Type::MainResource)
japhet@chromium.org3e317182013-01-29 20:06:19 +00003582 return;
3583
darin@apple.com837a78c2009-01-07 15:40:24 +00003584 if (!page->areMemoryCacheClientCallsEnabled()) {
cdumez@apple.comd038ecf2017-08-15 21:15:09 +00003585 InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
3586 m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource.resourceRequest());
commit-queue@webkit.org39359f02020-04-25 21:28:45 +00003587 m_documentLoader->didTellClientAboutLoad(resource.url().string());
darin@apple.com837a78c2009-01-07 15:40:24 +00003588 return;
3589 }
3590
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003591 if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), newRequest, resource.response(), resource.encodedSize())) {
cdumez@apple.comd038ecf2017-08-15 21:15:09 +00003592 InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), &resource);
commit-queue@webkit.org39359f02020-04-25 21:28:45 +00003593 m_documentLoader->didTellClientAboutLoad(resource.url().string());
timothy@apple.com8f85dce2008-01-08 23:51:28 +00003594 return;
3595 }
3596
anderscaec429f52007-01-13 01:44:24 +00003597 unsigned long identifier;
aestes@apple.com0c8e1912013-04-06 03:09:25 +00003598 requestFromDelegate(newRequest, identifier, error);
joepeck@webkit.orge7d264d2017-03-09 03:35:13 +00003599
cdumez@apple.comd038ecf2017-08-15 21:15:09 +00003600 ResourceResponse response = resource.response();
joepeck@webkit.orge7d264d2017-03-09 03:35:13 +00003601 response.setSource(ResourceResponse::Source::MemoryCache);
cdumez@apple.comd038ecf2017-08-15 21:15:09 +00003602 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, newRequest, response, 0, resource.encodedSize(), 0, error);
anderscade5715d2007-01-06 00:55:49 +00003603}
3604
Ms2ger@igalia.comc33b77c2017-11-10 16:41:03 +00003605void FrameLoader::applyUserAgentIfNeeded(ResourceRequest& request)
anderscade5715d2007-01-06 00:55:49 +00003606{
Ms2ger@igalia.comc33b77c2017-11-10 16:41:03 +00003607 if (!request.hasHTTPHeaderField(HTTPHeaderName::UserAgent)) {
3608 String userAgent = this->userAgent(request.url());
3609 ASSERT(!userAgent.isNull());
3610 request.setHTTPUserAgent(userAgent);
3611 }
anderscade5715d2007-01-06 00:55:49 +00003612}
3613
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003614bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const URL& url, unsigned long requestIdentifier)
weinig@apple.com5af461c2009-04-08 22:16:23 +00003615{
akling@apple.com52989472013-09-16 20:09:25 +00003616 Frame& topFrame = m_frame.tree().top();
3617 if (&m_frame == &topFrame)
weinig@apple.com5af461c2009-04-08 22:16:23 +00003618 return false;
3619
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003620 XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
3621
3622 switch (disposition) {
commit-queue@webkit.org27facab2020-07-18 10:33:54 +00003623 case XFrameOptionsDisposition::SameOrigin: {
yusukesuzuki@slowstart.orgae5a8bd2018-12-22 06:37:39 +00003624 auto origin = SecurityOrigin::create(url);
akling@apple.com52989472013-09-16 20:09:25 +00003625 if (!origin->isSameSchemeHostPort(topFrame.document()->securityOrigin()))
weinig@apple.com5af461c2009-04-08 22:16:23 +00003626 return true;
darin@apple.comfed4d162013-08-25 02:28:06 +00003627 for (Frame* frame = m_frame.tree().parent(); frame; frame = frame->tree().parent()) {
akling@apple.comfbea4062014-02-27 20:24:03 +00003628 if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin()))
dbates@webkit.org250656a2018-05-12 04:11:16 +00003629 return true;
mkwst@chromium.orgf9d8fa02013-03-19 21:12:24 +00003630 }
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003631 return false;
weinig@apple.com5af461c2009-04-08 22:16:23 +00003632 }
commit-queue@webkit.org27facab2020-07-18 10:33:54 +00003633 case XFrameOptionsDisposition::Deny:
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003634 return true;
commit-queue@webkit.org27facab2020-07-18 10:33:54 +00003635 case XFrameOptionsDisposition::AllowAll:
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003636 return false;
commit-queue@webkit.org27facab2020-07-18 10:33:54 +00003637 case XFrameOptionsDisposition::Conflict:
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00003638 m_frame.document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.stringCenterEllipsizedToLength() + "'. Falling back to 'DENY'.", requestIdentifier);
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003639 return true;
commit-queue@webkit.org27facab2020-07-18 10:33:54 +00003640 case XFrameOptionsDisposition::Invalid:
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00003641 m_frame.document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, "Invalid 'X-Frame-Options' header encountered when loading '" + url.stringCenterEllipsizedToLength() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier);
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003642 return false;
commit-queue@webkit.org27facab2020-07-18 10:33:54 +00003643 case XFrameOptionsDisposition::None:
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003644 return false;
3645 }
psolanki@apple.come2dc3b92014-02-20 18:23:24 +00003646 ASSERT_NOT_REACHED();
3647 return false;
weinig@apple.com5af461c2009-04-08 22:16:23 +00003648}
3649
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003650void FrameLoader::loadProvisionalItemFromCachedPage()
beidson50c3bd82007-01-03 03:11:18 +00003651{
achristensen@apple.comc41ad692019-01-31 21:23:44 +00003652 DocumentLoader* provisionalLoader = provisionalDocumentLoader();
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003653 LOG(BackForwardCache, "FrameLoader::loadProvisionalItemFromCachedPage Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().stringCenterEllipsizedToLength().utf8().data());
beidson@apple.comac095c02009-08-18 01:37:56 +00003654
achristensen@apple.comc41ad692019-01-31 21:23:44 +00003655 prepareForLoadStart();
3656
3657 m_loadingFromCachedPage = true;
3658
3659 // Should have timing data from previous time(s) the page was shown.
3660 ASSERT(provisionalLoader->timing().startTime());
3661 provisionalLoader->resetTiming();
3662 provisionalLoader->timing().markStartTime();
3663
3664 provisionalLoader->setCommitted(true);
3665 commitProvisionalLoad();
beidson50c3bd82007-01-03 03:11:18 +00003666}
3667
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003668bool FrameLoader::shouldTreatURLAsSameAsCurrent(const URL& url) const
beidson50c3bd82007-01-03 03:11:18 +00003669{
akling@apple.com672cb852013-08-22 20:27:27 +00003670 if (!history().currentItem())
beidson50c3bd82007-01-03 03:11:18 +00003671 return false;
akling@apple.com672cb852013-08-22 20:27:27 +00003672 return url == history().currentItem()->url() || url == history().currentItem()->originalURL();
beidson50c3bd82007-01-03 03:11:18 +00003673}
3674
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003675bool FrameLoader::shouldTreatURLAsSrcdocDocument(const URL& url) const
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00003676{
youenn@apple.com1779d582020-03-20 17:40:44 +00003677 if (!url.isAboutSrcDoc())
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00003678 return false;
akling@apple.com7f50aae2013-08-22 16:01:31 +00003679 HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement();
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00003680 if (!ownerElement)
3681 return false;
3682 if (!ownerElement->hasTagName(iframeTag))
3683 return false;
rniwa@webkit.orgbda54a02016-07-18 00:39:37 +00003684 return ownerElement->hasAttributeWithoutSynchronization(srcdocAttr);
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00003685}
3686
darin@apple.com0ce67df2019-06-17 01:48:13 +00003687Frame* FrameLoader::findFrameForNavigation(const AtomString& name, Document* activeDocument)
weinig@apple.com77427802008-01-11 00:23:13 +00003688{
ap@apple.comf8c414e2013-08-13 03:44:57 +00003689 // FIXME: Eventually all callers should supply the actual activeDocument so we can call canNavigate with the right document.
3690 if (!activeDocument)
akling@apple.com7f50aae2013-08-22 16:01:31 +00003691 activeDocument = m_frame.document();
ap@apple.comf8c414e2013-08-13 03:44:57 +00003692
cdumez@apple.com6cb3eff2018-10-15 15:34:39 +00003693 auto* frame = m_frame.tree().find(name, activeDocument->frame() ? *activeDocument->frame() : m_frame);
3694
ap@apple.comf8c414e2013-08-13 03:44:57 +00003695 if (!activeDocument->canNavigate(frame))
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003696 return nullptr;
abarth@webkit.orgb46fdef2012-04-13 00:42:37 +00003697
darin@apple.com0f88bda2009-04-02 00:30:50 +00003698 return frame;
weinig@apple.com77427802008-01-11 00:23:13 +00003699}
3700
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003701void FrameLoader::loadSameDocumentItem(HistoryItem& item)
beidson@apple.com08c61752009-12-03 19:04:40 +00003702{
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003703 ASSERT(item.documentSequenceNumber() == history().currentItem()->documentSequenceNumber());
beidson@apple.com08c61752009-12-03 19:04:40 +00003704
aestes@apple.com8303b342016-02-19 09:29:44 +00003705 Ref<Frame> protect(m_frame);
3706
beidson@apple.com08c61752009-12-03 19:04:40 +00003707 // Save user view state to the current history item here since we don't do a normal load.
3708 // FIXME: Does form state need to be saved here too?
akling@apple.com672cb852013-08-22 20:27:27 +00003709 history().saveScrollPositionAndViewStateToItem(history().currentItem());
akling@apple.com7f50aae2013-08-22 16:01:31 +00003710 if (FrameView* view = m_frame.view())
beidson@apple.com08c61752009-12-03 19:04:40 +00003711 view->setWasScrolledByUser(false);
3712
achristensen@apple.com3a889f12018-10-16 15:58:10 +00003713 history().setCurrentItem(item);
beidson@apple.com08c61752009-12-03 19:04:40 +00003714
3715 // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003716 loadInSameDocument(item.url(), item.stateObject(), false);
beidson@apple.com08c61752009-12-03 19:04:40 +00003717
3718 // Restore user view state from the current history item here since we don't do a normal load.
akling@apple.com672cb852013-08-22 20:27:27 +00003719 history().restoreScrollPositionAndViewState();
beidson@apple.com08c61752009-12-03 19:04:40 +00003720}
3721
abarth@webkit.org1c893f42009-10-10 02:27:21 +00003722// FIXME: This function should really be split into a couple pieces, some of
3723// which should be methods of HistoryController and some of which should be
3724// methods of FrameLoader.
cdumez@apple.com29f7c1e2019-03-13 20:32:48 +00003725void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, HistoryItem* fromItem, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
beidson50c3bd82007-01-03 03:11:18 +00003726{
krollin@apple.combdeaed72020-01-08 01:31:20 +00003727 FRAMELOADER_RELEASE_LOG_IF_ALLOWED(ResourceLoading, "loadDifferentDocumentItem: frame load started");
krollin@apple.come1810b62018-12-20 19:23:20 +00003728
bfulgham@apple.comd0c0fc82019-05-17 16:03:36 +00003729 Ref<Frame> protectedFrame(m_frame);
3730
jiewen_tan@apple.com71ef00e2018-12-04 23:01:29 +00003731 // History items should not be reported to the parent.
3732 m_shouldReportResourceTimingToParentFrame = false;
3733
beidson@apple.com08c61752009-12-03 19:04:40 +00003734 // Remember this item so we can traverse any child items as child frames load
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003735 history().setProvisionalItem(&item);
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003736
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00003737 auto initiatedByMainFrame = InitiatedByMainFrame::Unknown;
3738
cdumez@apple.com3aedc032019-01-31 02:23:55 +00003739 SetForScope<LoadContinuingState> continuingLoadGuard(m_currentLoadContinuingState, shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::Yes ? LoadContinuingState::ContinuingWithHistoryItem : LoadContinuingState::NotContinuing);
beidson@apple.com69caeee2018-04-20 04:55:32 +00003740
cdumez@apple.com9265dfe2019-10-17 01:44:16 +00003741 if (CachedPage* cachedPage = BackForwardCache::singleton().get(item, m_frame.page())) {
mitz@apple.com4a604422014-11-13 23:22:50 +00003742 auto documentLoader = cachedPage->documentLoader();
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003743 m_client->updateCachedDocumentLoader(*documentLoader);
beidson@apple.com07c00cf2018-05-11 16:12:11 +00003744
3745 auto action = NavigationAction { *m_frame.document(), documentLoader->request(), initiatedByMainFrame, loadType, false };
3746 action.setTargetBackForwardItem(item);
cdumez@apple.com29f7c1e2019-03-13 20:32:48 +00003747 action.setSourceBackForwardItem(fromItem);
beidson@apple.com07c00cf2018-05-11 16:12:11 +00003748 documentLoader->setTriggeringAction(WTFMove(action));
3749
mitz@apple.com4a604422014-11-13 23:22:50 +00003750 documentLoader->setLastCheckedRequest(ResourceRequest());
commit-queue@webkit.org372c2642020-04-03 16:53:48 +00003751 loadWithDocumentLoader(documentLoader, loadType, { }, AllowNavigationToInvalidURL::Yes);
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003752 return;
beidson@apple.com08c61752009-12-03 19:04:40 +00003753 }
adele@apple.comf3d6b892008-04-29 01:30:20 +00003754
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003755 URL itemURL = item.url();
3756 URL itemOriginalURL = item.originalURL();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003757 URL currentURL;
beidson0c345992007-02-13 08:59:33 +00003758 if (documentLoader())
weinig@apple.comc5002662007-12-12 07:26:19 +00003759 currentURL = documentLoader()->url();
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003760 RefPtr<FormData> formData = item.formData();
beidson50c3bd82007-01-03 03:11:18 +00003761
beidson@apple.com08c61752009-12-03 19:04:40 +00003762 ResourceRequest request(itemURL);
3763
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003764 if (!item.referrer().isNull())
3765 request.setHTTPReferrer(item.referrer());
dbates@webkit.orgae34b602015-08-05 16:05:55 +00003766
dbates@webkit.org9692a072017-07-12 18:01:19 +00003767 ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(m_frame, initiatedByMainFrame, item.shouldOpenExternalURLsPolicy());
dbates@webkit.orgae34b602015-08-05 16:05:55 +00003768 bool isFormSubmission = false;
3769 Event* event = nullptr;
3770
beidson@apple.com08c61752009-12-03 19:04:40 +00003771 // If this was a repost that failed the page cache, we might try to repost the form.
3772 NavigationAction action;
3773 if (formData) {
beidson@apple.com08c61752009-12-03 19:04:40 +00003774 request.setHTTPMethod("POST");
youenn.fablet@crf.canon.fr11cc6552016-01-22 14:51:16 +00003775 request.setHTTPBody(WTFMove(formData));
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003776 request.setHTTPContentType(item.formContentType());
cdumez@apple.com1f985b82020-05-01 23:07:38 +00003777 auto securityOrigin = SecurityOrigin::createFromString(item.referrer());
3778 addHTTPOriginIfNeeded(request, securityOrigin->toString());
beidson@apple.com08c61752009-12-03 19:04:40 +00003779
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00003780 addExtraFieldsToRequest(request, IsMainResource::Yes, loadType);
beidson@apple.com08c61752009-12-03 19:04:40 +00003781
3782 // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3783 // We want to know this before talking to the policy delegate, since it affects whether
3784 // we show the DoYouReallyWantToRepost nag.
3785 //
3786 // This trick has a small bug (3123893) where we might find a cache hit, but then
3787 // have the item vanish when we try to use it in the ensuing nav. This should be
3788 // extremely rare, but in that case the user will get an error on the navigation.
3789
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003790 if (cacheLoadPolicy == MayAttemptCacheOnlyLoadForFormSubmissionItem) {
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00003791 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataDontLoad);
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00003792 action = { *m_frame.document(), request, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003793 } else {
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00003794 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00003795 action = { *m_frame.document(), request, initiatedByMainFrame, NavigationType::FormResubmitted, shouldOpenExternalURLsPolicy, event };
beidson@apple.com08c61752009-12-03 19:04:40 +00003796 }
3797 } else {
3798 switch (loadType) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003799 case FrameLoadType::Reload:
commit-queue@webkit.orgea87ad82018-01-11 00:45:49 +00003800 case FrameLoadType::ReloadFromOrigin:
commit-queue@webkit.org4833ac52018-02-26 17:38:14 +00003801 case FrameLoadType::ReloadExpiredOnly:
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00003802 request.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003803 break;
3804 case FrameLoadType::Back:
3805 case FrameLoadType::Forward:
carlosgc@webkit.org2af15b72016-02-27 07:44:07 +00003806 case FrameLoadType::IndexedBackForward: {
cdumez@apple.com3e885d42016-03-15 20:01:39 +00003807#if PLATFORM(COCOA)
carlosgc@webkit.org2af15b72016-02-27 07:44:07 +00003808 bool allowStaleData = true;
3809#else
3810 bool allowStaleData = !item.wasRestoredFromSession();
3811#endif
3812 if (allowStaleData)
simon.fraser@apple.com90e96252018-07-09 23:54:18 +00003813 request.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
carlosgc@webkit.org2af15b72016-02-27 07:44:07 +00003814 item.setWasRestoredFromSession(false);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003815 break;
carlosgc@webkit.org2af15b72016-02-27 07:44:07 +00003816 }
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003817 case FrameLoadType::Standard:
3818 case FrameLoadType::RedirectWithLockedBackForwardList:
3819 break;
3820 case FrameLoadType::Same:
antti@apple.com5d0c5402017-03-17 19:52:49 +00003821 case FrameLoadType::Replace:
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003822 ASSERT_NOT_REACHED();
beidson@apple.com08c61752009-12-03 19:04:40 +00003823 }
3824
commit-queue@webkit.org627a2de2020-04-13 08:04:39 +00003825 addExtraFieldsToRequest(request, IsMainResource::Yes, loadType);
beidson@apple.com08c61752009-12-03 19:04:40 +00003826
jochen@chromium.org056b7fa2011-10-18 04:47:05 +00003827 ResourceRequest requestForOriginalURL(request);
3828 requestForOriginalURL.setURL(itemOriginalURL);
dbates@webkit.org9692a072017-07-12 18:01:19 +00003829 action = { *m_frame.document(), requestForOriginalURL, initiatedByMainFrame, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy };
jochen@chromium.org056b7fa2011-10-18 04:47:05 +00003830 }
3831
beidson@apple.com07c00cf2018-05-11 16:12:11 +00003832 action.setTargetBackForwardItem(item);
cdumez@apple.com29f7c1e2019-03-13 20:32:48 +00003833 action.setSourceBackForwardItem(fromItem);
beidson@apple.com07c00cf2018-05-11 16:12:11 +00003834
commit-queue@webkit.org4a7ad282020-04-05 05:09:42 +00003835 loadWithNavigationAction(request, WTFMove(action), loadType, { }, AllowNavigationToInvalidURL::Yes);
beidson@apple.com08c61752009-12-03 19:04:40 +00003836}
3837
3838// Loads content into this frame, as specified by history item
cdumez@apple.com29f7c1e2019-03-13 20:32:48 +00003839void FrameLoader::loadItem(HistoryItem& item, HistoryItem* fromItem, FrameLoadType loadType, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad)
beidson@apple.com08c61752009-12-03 19:04:40 +00003840{
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003841 m_requestedHistoryItem = &item;
akling@apple.com672cb852013-08-22 20:27:27 +00003842 HistoryItem* currentItem = history().currentItem();
cdumez@apple.comfea5cb92015-02-02 00:49:36 +00003843 bool sameDocumentNavigation = currentItem && item.shouldDoSameDocumentNavigationTo(*currentItem);
darin@chromium.orge71dd0f2009-04-17 20:31:17 +00003844
cdumez@apple.com4c2d2282020-10-29 21:35:14 +00003845 // If we're continuing this history navigation in a new process, then doing a same document navigation never makes sense.
3846 ASSERT(!sameDocumentNavigation || shouldTreatAsContinuingLoad == ShouldTreatAsContinuingLoad::No);
3847
beidson@apple.com08c61752009-12-03 19:04:40 +00003848 if (sameDocumentNavigation)
mihaip@chromium.orge5dbd372010-12-08 02:32:41 +00003849 loadSameDocumentItem(item);
beidson@apple.com08c61752009-12-03 19:04:40 +00003850 else
cdumez@apple.com29f7c1e2019-03-13 20:32:48 +00003851 loadDifferentDocumentItem(item, fromItem, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem, shouldTreatAsContinuingLoad);
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003852}
3853
3854void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
3855{
3856 ASSERT(m_state == FrameStateProvisional);
3857 ASSERT(!m_loadingFromCachedPage);
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003858 ASSERT(history().provisionalItem());
akling@apple.com672cb852013-08-22 20:27:27 +00003859 ASSERT(history().provisionalItem()->formData());
3860 ASSERT(history().provisionalItem() == m_requestedHistoryItem.get());
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003861
3862 FrameLoadType loadType = m_loadType;
achristensen@apple.comd9245762019-07-09 18:55:43 +00003863 HistoryItem* item = history().provisionalItem();
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003864
3865 stopAllLoaders(ShouldNotClearProvisionalItem);
achristensen@apple.comd9245762019-07-09 18:55:43 +00003866 if (item)
3867 loadDifferentDocumentItem(*item, history().currentItem(), loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem, ShouldTreatAsContinuingLoad::No);
3868 else {
3869 ASSERT_NOT_REACHED();
krollin@apple.comf26b56e2020-02-28 19:43:33 +00003870 FRAMELOADER_RELEASE_LOG_ERROR_IF_ALLOWED(ResourceLoading, "retryAfterFailedCacheOnlyMainResourceLoad: Retrying load after failed cache-only main resource load failed because there is no provisional history item.");
achristensen@apple.comd9245762019-07-09 18:55:43 +00003871 }
beidson50c3bd82007-01-03 03:11:18 +00003872}
3873
anderscac8ee2462007-01-05 22:26:32 +00003874ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
3875{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003876 ResourceError error = m_client->cancelledError(request);
youenn.fablet@crf.canon.fr156f9bb2016-06-09 06:55:26 +00003877 error.setType(ResourceError::Type::Cancellation);
weinig@apple.com87a569c2008-05-18 01:21:20 +00003878 return error;
anderscac8ee2462007-01-05 22:26:32 +00003879}
3880
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +00003881ResourceError FrameLoader::blockedByContentBlockerError(const ResourceRequest& request) const
3882{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003883 return m_client->blockedByContentBlockerError(request);
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +00003884}
3885
bfulgham@apple.comb4c70932016-01-06 22:07:51 +00003886ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
3887{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003888 ResourceError error = m_client->blockedError(request);
youenn.fablet@crf.canon.fr156f9bb2016-06-09 06:55:26 +00003889 error.setType(ResourceError::Type::Cancellation);
bfulgham@apple.comb4c70932016-01-06 22:07:51 +00003890 return error;
3891}
3892
aestes@apple.com176a9aa2016-07-08 20:14:34 +00003893#if ENABLE(CONTENT_FILTERING)
3894ResourceError FrameLoader::blockedByContentFilterError(const ResourceRequest& request) const
3895{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003896 ResourceError error = m_client->blockedByContentFilterError(request);
aestes@apple.com176a9aa2016-07-08 20:14:34 +00003897 error.setType(ResourceError::Type::General);
3898 return error;
3899}
3900#endif
3901
ap@apple.com1e8475922018-10-18 21:38:50 +00003902#if PLATFORM(IOS_FAMILY)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00003903RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loader)
3904{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003905 return m_client->connectionProperties(loader->documentLoader(), loader->identifier());
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00003906}
3907#endif
3908
dbates@webkit.org0fefad72017-10-19 18:46:22 +00003909ReferrerPolicy FrameLoader::effectiveReferrerPolicy() const
3910{
3911 if (auto* parentFrame = m_frame.tree().parent())
3912 return parentFrame->document()->referrerPolicy();
3913 if (m_opener)
3914 return m_opener->document()->referrerPolicy();
3915 return ReferrerPolicy::NoReferrerWhenDowngrade;
3916}
3917
andersca4422e372007-01-12 19:56:19 +00003918String FrameLoader::referrer() const
3919{
cdumez@apple.com327d6c62016-07-16 04:51:45 +00003920 return m_documentLoader ? m_documentLoader->request().httpReferrer() : emptyString();
andersca4422e372007-01-12 19:56:19 +00003921}
3922
aroben@apple.com11dd5262009-11-13 23:49:05 +00003923void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
lars1e1dad32007-01-23 10:28:38 +00003924{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003925 if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
thatcher10840e52007-09-22 00:49:09 +00003926 return;
3927
weinig@apple.com8f716032013-10-02 17:03:09 +00003928 Vector<Ref<DOMWrapperWorld>> worlds;
aroben@apple.com11dd5262009-11-13 23:49:05 +00003929 ScriptController::getAllWorlds(worlds);
cdumez@apple.com2f661202014-11-04 07:22:18 +00003930 for (auto& world : worlds)
3931 dispatchDidClearWindowObjectInWorld(world);
aroben@apple.com11dd5262009-11-13 23:49:05 +00003932}
3933
weinig@apple.com8f716032013-10-02 17:03:09 +00003934void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
aroben@apple.com11dd5262009-11-13 23:49:05 +00003935{
cdumez@apple.com87a798a2018-04-19 04:02:30 +00003936 if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.windowProxy().existingJSWindowProxy(world))
aroben@apple.com11dd5262009-11-13 23:49:05 +00003937 return;
3938
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003939 m_client->dispatchDidClearWindowObjectInWorld(world);
timothy@apple.comefb8ac12008-07-24 02:48:36 +00003940
akling@apple.com7f50aae2013-08-22 16:01:31 +00003941 if (Page* page = m_frame.page())
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003942 page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
loislo@chromium.orge971cb52011-02-08 17:32:44 +00003943
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003944 InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
lars1e1dad32007-01-23 10:28:38 +00003945}
3946
beidson@apple.com2a75a962012-04-24 18:12:55 +00003947void FrameLoader::dispatchGlobalObjectAvailableInAllWorlds()
3948{
weinig@apple.com8f716032013-10-02 17:03:09 +00003949 Vector<Ref<DOMWrapperWorld>> worlds;
beidson@apple.com2a75a962012-04-24 18:12:55 +00003950 ScriptController::getAllWorlds(worlds);
cdumez@apple.com2f661202014-11-04 07:22:18 +00003951 for (auto& world : worlds)
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003952 m_client->dispatchGlobalObjectAvailable(world);
beidson@apple.com2a75a962012-04-24 18:12:55 +00003953}
3954
abarth@webkit.org8b45d862011-11-05 21:55:59 +00003955SandboxFlags FrameLoader::effectiveSandboxFlags() const
abarth@webkit.orgb8a10552009-12-02 02:40:35 +00003956{
abarth@webkit.orgf2c54c22010-04-11 06:57:13 +00003957 SandboxFlags flags = m_forcedSandboxFlags;
darin@apple.comfed4d162013-08-25 02:28:06 +00003958 if (Frame* parentFrame = m_frame.tree().parent())
abarth@webkit.org8b45d862011-11-05 21:55:59 +00003959 flags |= parentFrame->document()->sandboxFlags();
akling@apple.com7f50aae2013-08-22 16:01:31 +00003960 if (HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement())
abarth@webkit.orgb8a10552009-12-02 02:40:35 +00003961 flags |= ownerElement->sandboxFlags();
abarth@webkit.org8b45d862011-11-05 21:55:59 +00003962 return flags;
abarth@webkit.orgf5267a42010-01-10 08:14:05 +00003963}
abarth@webkit.orgb8a10552009-12-02 02:40:35 +00003964
lars1e1dad32007-01-23 10:28:38 +00003965void FrameLoader::didChangeTitle(DocumentLoader* loader)
3966{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003967 m_client->didChangeTitle(loader);
lars1e1dad32007-01-23 10:28:38 +00003968
darin@apple.com719d29c2009-07-24 00:09:17 +00003969 if (loader == m_documentLoader) {
lars1e1dad32007-01-23 10:28:38 +00003970 // Must update the entries in the back-forward list too.
akling@apple.com672cb852013-08-22 20:27:27 +00003971 history().setCurrentItemTitle(loader->title());
lars1e1dad32007-01-23 10:28:38 +00003972 // This must go through the WebFrame because it has the right notion of the current b/f item.
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003973 m_client->setTitle(loader->title(), loader->urlForHistory());
3974 m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
3975 m_client->dispatchDidReceiveTitle(loader->title());
lars1e1dad32007-01-23 10:28:38 +00003976 }
joepeck@webkit.orgd2ecf372013-12-04 18:20:37 +00003977
3978#if ENABLE(REMOTE_INSPECTOR)
3979 if (m_frame.isMainFrame())
3980 m_frame.page()->remoteInspectorInformationDidChange();
3981#endif
lars1e1dad32007-01-23 10:28:38 +00003982}
andersca4422e372007-01-12 19:56:19 +00003983
achristensen@apple.come0301a32020-02-07 23:30:29 +00003984void FrameLoader::dispatchDidCommitLoad(Optional<HasInsecureContent> initialHasInsecureContent, Optional<UsedLegacyTLS> initialUsedLegacyTLS)
arobendfc56662007-06-21 01:37:24 +00003985{
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00003986 if (m_stateMachine.creatingInitialEmptyDocument())
darin@apple.com87134f22007-12-05 22:58:41 +00003987 return;
3988
youenn@apple.comee96d0f2020-03-18 13:59:23 +00003989 m_client->dispatchDidCommitLoad(initialHasInsecureContent, initialUsedLegacyTLS);
arobendfc56662007-06-21 01:37:24 +00003990
simon.fraser@apple.com54d77572020-08-04 05:57:39 +00003991 if (m_frame.isMainFrame())
3992 m_frame.page()->didCommitLoad();
jer.noble@apple.com381b4672012-07-28 00:41:18 +00003993
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003994 InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
commit-queue@webkit.org42b47872013-02-19 19:19:02 +00003995
joepeck@webkit.orgd2ecf372013-12-04 18:20:37 +00003996#if ENABLE(REMOTE_INSPECTOR)
akling@apple.comfbea4062014-02-27 20:24:03 +00003997 if (m_frame.isMainFrame())
joepeck@webkit.orgd2ecf372013-12-04 18:20:37 +00003998 m_frame.page()->remoteInspectorInformationDidChange();
3999#endif
arobendfc56662007-06-21 01:37:24 +00004000}
4001
darin@apple.com837a78c2009-01-07 15:40:24 +00004002void FrameLoader::tellClientAboutPastMemoryCacheLoads()
4003{
akling@apple.com7f50aae2013-08-22 16:01:31 +00004004 ASSERT(m_frame.page());
4005 ASSERT(m_frame.page()->areMemoryCacheClientCallsEnabled());
darin@apple.com837a78c2009-01-07 15:40:24 +00004006
4007 if (!m_documentLoader)
4008 return;
4009
jpfau@apple.com97c6a7f2013-02-26 00:49:17 +00004010 Vector<ResourceRequest> pastLoads;
darin@apple.com837a78c2009-01-07 15:40:24 +00004011 m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
4012
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00004013 for (auto& pastLoad : pastLoads) {
4014 CachedResource* resource = MemoryCache::singleton().resourceForRequest(pastLoad, m_frame.page()->sessionID());
darin@apple.com837a78c2009-01-07 15:40:24 +00004015
4016 // FIXME: These loads, loaded from cache, but now gone from the cache by the time
4017 // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
4018 // Consider if there's some efficient way of remembering enough to deliver this client call.
4019 // We have the URL, but not the rest of the response or the length.
4020 if (!resource)
4021 continue;
4022
4023 ResourceRequest request(resource->url());
youenn@apple.comee96d0f2020-03-18 13:59:23 +00004024 m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
darin@apple.com837a78c2009-01-07 15:40:24 +00004025 }
4026}
4027
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +00004028NetworkingContext* FrameLoader::networkingContext() const
4029{
4030 return m_networkingContext.get();
4031}
4032
antti@apple.coma6775c12013-04-05 21:19:56 +00004033void FrameLoader::loadProgressingStatusChanged()
4034{
antti@apple.com08536d12014-06-27 21:58:06 +00004035 if (auto* view = m_frame.mainFrame().view())
4036 view->loadProgressingStatusChanged();
antti@apple.coma6775c12013-04-05 21:19:56 +00004037}
4038
zalan@apple.comfc7ad742020-03-04 14:53:01 +00004039void FrameLoader::completePageTransitionIfNeeded()
timothy_horton@apple.com88756d62013-05-30 06:24:36 +00004040{
youenn@apple.comee96d0f2020-03-18 13:59:23 +00004041 m_client->completePageTransitionIfNeeded();
timothy_horton@apple.com88756d62013-05-30 06:24:36 +00004042}
4043
antti@apple.com1229ead2015-03-30 21:09:14 +00004044void FrameLoader::clearTestingOverrides()
4045{
cdumez@apple.com8b7a0222018-12-20 04:41:11 +00004046 m_overrideCachePolicyForTesting = WTF::nullopt;
4047 m_overrideResourceLoadPriorityForTesting = WTF::nullopt;
antti@apple.com2c4a2a22015-08-14 14:08:59 +00004048 m_isStrictRawResourceValidationPolicyDisabledForTesting = false;
antti@apple.com1229ead2015-03-30 21:09:14 +00004049}
4050
commit-queue@webkit.org6d635222016-03-08 06:44:59 +00004051bool FrameLoader::isAlwaysOnLoggingAllowed() const
4052{
4053 return frame().isAlwaysOnLoggingAllowed();
4054}
4055
darin@apple.com90a0f152009-02-01 00:55:03 +00004056bool FrameLoaderClient::hasHTMLView() const
4057{
4058 return true;
4059}
4060
dbates@webkit.org7f3a9822017-06-22 19:45:10 +00004061RefPtr<Frame> createWindow(Frame& openerFrame, Frame& lookupFrame, FrameLoadRequest&& request, const WindowFeatures& features, bool& created)
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004062{
4063 ASSERT(!features.dialog || request.frameName().isEmpty());
commit-queue@webkit.org8a13ad32020-03-16 08:11:26 +00004064 ASSERT(request.resourceRequest().httpMethod() == "GET");
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004065
darin@apple.com14800c12014-04-27 04:09:45 +00004066 created = false;
4067
dbates@webkit.orgde972cd2018-01-24 22:11:19 +00004068 // FIXME: Provide line number information with respect to the opener's document.
commit-queue@webkit.org39359f02020-04-25 21:28:45 +00004069 if (request.resourceRequest().url().protocolIsJavaScript() && !openerFrame.document()->contentSecurityPolicy()->allowJavaScriptURLs(openerFrame.document()->url().string(), { }))
dbates@webkit.orgde972cd2018-01-24 22:11:19 +00004070 return nullptr;
4071
cdumez@apple.comeec032f2017-04-05 13:36:47 +00004072 if (!request.frameName().isEmpty() && !equalIgnoringASCIICase(request.frameName(), "_blank")) {
cdumez@apple.com468ca182015-05-15 05:07:22 +00004073 if (RefPtr<Frame> frame = lookupFrame.loader().findFrameForNavigation(request.frameName(), openerFrame.document())) {
cdumez@apple.comeec032f2017-04-05 13:36:47 +00004074 if (!equalIgnoringASCIICase(request.frameName(), "_self")) {
jochen@chromium.orgb2c684a2013-05-11 19:09:01 +00004075 if (Page* page = frame->page())
akling@apple.combd774812013-05-17 00:03:01 +00004076 page->chrome().focus();
jochen@chromium.orgb2c684a2013-05-11 19:09:01 +00004077 }
aestes@apple.com2038dcb2015-12-28 16:26:24 +00004078 return frame;
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004079 }
4080 }
4081
4082 // Sandboxed frames cannot open new auxiliary browsing contexts.
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +00004083 if (isDocumentSandboxed(openerFrame, SandboxPopups)) {
4084 // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
cdumez@apple.comd6738dc2015-05-04 23:58:32 +00004085 openerFrame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked opening '" + request.resourceRequest().url().stringCenterEllipsizedToLength() + "' in a new window because the request was made in a sandboxed frame whose 'allow-popups' permission is not set.");
darin@apple.com14800c12014-04-27 04:09:45 +00004086 return nullptr;
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +00004087 }
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004088
4089 // FIXME: Setting the referrer should be the caller's responsibility.
cdumez@apple.comd6738dc2015-05-04 23:58:32 +00004090 String referrer = SecurityPolicy::generateReferrerHeader(openerFrame.document()->referrerPolicy(), request.resourceRequest().url(), openerFrame.loader().outgoingReferrer());
jochen@chromium.orgc881e402013-02-28 21:45:58 +00004091 if (!referrer.isEmpty())
dbates@webkit.org7f3a9822017-06-22 19:45:10 +00004092 request.resourceRequest().setHTTPReferrer(referrer);
dbates@webkit.org8c917f22018-04-24 07:36:59 +00004093 FrameLoader::addSameSiteInfoToRequestIfNeeded(request.resourceRequest(), openerFrame.document());
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004094
cdumez@apple.comd6738dc2015-05-04 23:58:32 +00004095 Page* oldPage = openerFrame.page();
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004096 if (!oldPage)
darin@apple.com14800c12014-04-27 04:09:45 +00004097 return nullptr;
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004098
beidson@apple.com7034ec72017-07-06 00:01:53 +00004099 ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(openerFrame, request);
dbates@webkit.orgc49c95d2017-07-12 17:25:37 +00004100 NavigationAction action { request.requester(), request.resourceRequest(), request.initiatedByMainFrame(), NavigationType::Other, shouldOpenExternalURLsPolicy };
commit-queue@webkit.orgba637602020-03-16 07:20:28 +00004101 Page* page = oldPage->chrome().createWindow(openerFrame, features, action);
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004102 if (!page)
darin@apple.com14800c12014-04-27 04:09:45 +00004103 return nullptr;
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004104
darin@apple.com14800c12014-04-27 04:09:45 +00004105 RefPtr<Frame> frame = &page->mainFrame();
4106
commit-queue@webkit.org04df8422017-06-09 17:59:18 +00004107 if (isDocumentSandboxed(openerFrame, SandboxPropagatesToAuxiliaryBrowsingContexts))
4108 frame->loader().forceSandboxFlags(openerFrame.document()->sandboxFlags());
abarth@webkit.org7155e252011-11-04 18:14:58 +00004109
cdumez@apple.comeec032f2017-04-05 13:36:47 +00004110 if (!equalIgnoringASCIICase(request.frameName(), "_blank"))
darin@apple.com14800c12014-04-27 04:09:45 +00004111 frame->tree().setName(request.frameName());
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004112
akling@apple.combd774812013-05-17 00:03:01 +00004113 page->chrome().setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00004114
4115 if (!frame->page())
4116 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00004117 page->chrome().setStatusbarVisible(features.statusBarVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00004118
4119 if (!frame->page())
4120 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00004121 page->chrome().setScrollbarsVisible(features.scrollbarsVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00004122
4123 if (!frame->page())
4124 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00004125 page->chrome().setMenubarVisible(features.menuBarVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00004126
4127 if (!frame->page())
4128 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00004129 page->chrome().setResizable(features.resizable);
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004130
4131 // 'x' and 'y' specify the location of the window, while 'width' and 'height'
kenneth@webkit.orgdc092f72012-11-14 11:05:20 +00004132 // specify the size of the viewport. We can only resize the window, so adjust
4133 // for the difference between the window size and the viewport size.
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004134
darin@apple.com14800c12014-04-27 04:09:45 +00004135 // FIXME: We should reconcile the initialization of viewport arguments between iOS and non-IOS.
ap@apple.com1e8475922018-10-18 21:38:50 +00004136#if !PLATFORM(IOS_FAMILY)
akling@apple.combd774812013-05-17 00:03:01 +00004137 FloatSize viewportSize = page->chrome().pageRect().size();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00004138 FloatRect windowRect = page->chrome().windowRect();
andersca@apple.comc1242ad2015-08-13 17:37:27 +00004139 if (features.x)
4140 windowRect.setX(*features.x);
4141 if (features.y)
4142 windowRect.setY(*features.y);
clopez@igalia.com6251d342020-04-16 11:22:51 +00004143 // Zero width and height mean using default size, not minimum one.
andersca@apple.comc1242ad2015-08-13 17:37:27 +00004144 if (features.width && *features.width)
4145 windowRect.setWidth(*features.width + (windowRect.width() - viewportSize.width()));
4146 if (features.height && *features.height)
4147 windowRect.setHeight(*features.height + (windowRect.height() - viewportSize.height()));
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004148
clopez@igalia.com6251d342020-04-16 11:22:51 +00004149#if PLATFORM(GTK)
4150 FloatRect oldWindowRect = oldPage->chrome().windowRect();
4151 // Use the size of the previous window if there is no default size.
4152 if (!windowRect.width())
4153 windowRect.setWidth(oldWindowRect.width());
4154 if (!windowRect.height())
4155 windowRect.setHeight(oldWindowRect.height());
4156#endif
4157
kenneth@webkit.orgdc092f72012-11-14 11:05:20 +00004158 // Ensure non-NaN values, minimum size as well as being within valid screen area.
darin@apple.com9ace8012017-01-23 06:24:18 +00004159 FloatRect newWindowRect = DOMWindow::adjustWindowRect(*page, windowRect);
kenneth@webkit.orgdc092f72012-11-14 11:05:20 +00004160
darin@apple.com14800c12014-04-27 04:09:45 +00004161 if (!frame->page())
4162 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00004163 page->chrome().setWindowRect(newWindowRect);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00004164#else
4165 // On iOS, width and height refer to the viewport dimensions.
4166 ViewportArguments arguments;
4167 // Zero width and height mean using default size, not minimum one.
andersca@apple.comc1242ad2015-08-13 17:37:27 +00004168 if (features.width && *features.width)
4169 arguments.width = *features.width;
4170 if (features.height && *features.height)
4171 arguments.height = *features.height;
darin@apple.com14800c12014-04-27 04:09:45 +00004172 frame->setViewportArguments(arguments);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00004173#endif
4174
darin@apple.com14800c12014-04-27 04:09:45 +00004175 if (!frame->page())
4176 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00004177 page->chrome().show();
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004178
4179 created = true;
aestes@apple.com2038dcb2015-12-28 16:26:24 +00004180 return frame;
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00004181}
4182
timothy_horton@apple.com57a22212017-10-19 20:43:41 +00004183bool FrameLoader::shouldSuppressTextInputFromEditing() const
aestes@apple.com54c9cf52016-12-16 23:10:56 +00004184{
timothy_horton@apple.com57a22212017-10-19 20:43:41 +00004185 return m_frame.settings().shouldSuppressTextInputFromEditingDuringProvisionalNavigation() && m_state == FrameStateProvisional;
aestes@apple.com54c9cf52016-12-16 23:10:56 +00004186}
4187
commit-queue@webkit.org95298582020-04-17 07:52:00 +00004188bool FrameLoader::arePluginsEnabled()
4189{
4190 return m_frame.settings().arePluginsEnabled();
4191}
4192
ggaren58e230c2006-11-12 04:53:17 +00004193} // namespace WebCore
krollin@apple.comf26b56e2020-02-28 19:43:33 +00004194
4195#undef PAGE_ID
4196#undef FRAME_ID