blob: 9d061996d7736d69a016bb0527e8d35d350161e6 [file] [log] [blame]
darinfa7a4e32006-10-30 00:37:02 +00001/*
aestes@apple.com5e143732011-03-25 23:07:43 +00002 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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"
darin@apple.come10e1282010-10-30 00:44:33 +000040#include "BackForwardController.h"
beidson@apple.com7617ce72010-05-13 20:31:46 +000041#include "BeforeUnloadEvent.h"
beidson448a6e72007-04-10 23:55:56 +000042#include "CachedPage.h"
darin@apple.come10e1282010-10-30 00:44:33 +000043#include "CachedResourceLoader.h"
ggaren52fd1072006-11-06 23:56:59 +000044#include "Chrome.h"
commit-queue@webkit.org52b68332011-06-07 16:20:07 +000045#include "ChromeClient.h"
abarth@webkit.orgf921dee2011-03-26 11:59:34 +000046#include "ContentSecurityPolicy.h"
darinc370e7e2006-11-08 05:52:27 +000047#include "DOMImplementation.h"
aroben@apple.com92cfa902008-04-16 19:19:00 +000048#include "DOMWindow.h"
mark.lam@apple.com45beb072012-12-12 23:04:20 +000049#include "DatabaseManager.h"
jer.noble@apple.com9e0f0602014-11-22 05:27:16 +000050#include "DiagnosticLoggingClient.h"
eric.carlson@apple.com77b4a112014-10-30 19:04:29 +000051#include "DiagnosticLoggingKeys.h"
darinc370e7e2006-11-08 05:52:27 +000052#include "Document.h"
tonyg@chromium.org064638a2010-07-26 17:03:35 +000053#include "DocumentLoadTiming.h"
darinc1116552006-10-30 20:05:39 +000054#include "DocumentLoader.h"
darinc370e7e2006-11-08 05:52:27 +000055#include "Editor.h"
anderscaf6232012006-11-15 00:36:50 +000056#include "EditorClient.h"
ggaren52fd1072006-11-06 23:56:59 +000057#include "Element.h"
darinf1bb0042006-12-01 22:46:21 +000058#include "Event.h"
weinig@apple.com13d777f2013-04-16 21:54:22 +000059#include "EventHandler.h"
darinc370e7e2006-11-08 05:52:27 +000060#include "EventNames.h"
ggaren52fd1072006-11-06 23:56:59 +000061#include "FloatRect.h"
darinc1116552006-10-30 20:05:39 +000062#include "FormState.h"
dglazkov@chromium.org25a57e52010-06-20 21:00:35 +000063#include "FormSubmission.h"
ggaren52fd1072006-11-06 23:56:59 +000064#include "FrameLoadRequest.h"
65#include "FrameLoaderClient.h"
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +000066#include "FrameNetworkingContext.h"
ggaren52fd1072006-11-06 23:56:59 +000067#include "FrameTree.h"
darinc370e7e2006-11-08 05:52:27 +000068#include "FrameView.h"
japhet@chromium.org3ded9632009-10-19 21:15:06 +000069#include "HTMLAnchorElement.h"
darinc370e7e2006-11-08 05:52:27 +000070#include "HTMLFormElement.h"
commit-queue@webkit.orge5739ca2012-11-15 19:39:50 +000071#include "HTMLInputElement.h"
darinc370e7e2006-11-08 05:52:27 +000072#include "HTMLNames.h"
73#include "HTMLObjectElement.h"
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +000074#include "HTMLParserIdioms.h"
andersca@apple.coma96cf712014-06-14 17:49:44 +000075#include "HTTPHeaderNames.h"
ape9991d52006-12-08 18:19:51 +000076#include "HTTPParsers.h"
andersca@apple.com9b9d83b2013-04-10 19:11:20 +000077#include "HistoryController.h"
weinig62f94be2007-07-18 20:37:20 +000078#include "HistoryItem.h"
andersca@apple.com9b9d83b2013-04-10 19:11:20 +000079#include "IconController.h"
commit-queue@webkit.org4c49a662011-01-02 22:27:10 +000080#include "InspectorController.h"
yurys@chromium.org389a6242011-01-12 13:06:42 +000081#include "InspectorInstrumentation.h"
beidson@apple.com0c140b42013-01-17 00:45:30 +000082#include "LoaderStrategy.h"
beidson50c3bd82007-01-03 03:11:18 +000083#include "Logging.h"
weinig62f94be2007-07-18 20:37:20 +000084#include "MIMETypeRegistry.h"
darin@apple.comade301a2013-09-27 15:09:01 +000085#include "MainFrame.h"
weinig@apple.com13d777f2013-04-16 21:54:22 +000086#include "MemoryCache.h"
ggaren2e941232007-05-26 00:28:27 +000087#include "PageCache.h"
barraclough@apple.com58899e02014-02-12 21:56:32 +000088#include "PageThrottler.h"
ggaren@apple.com521f64b2009-09-24 05:53:23 +000089#include "PageTransitionEvent.h"
beidson@apple.com0c140b42013-01-17 00:45:30 +000090#include "PlatformStrategies.h"
hausmann@webkit.org9999bb82008-03-10 11:52:27 +000091#include "PluginData.h"
andersca@apple.com641fef92009-01-06 22:57:25 +000092#include "PluginDocument.h"
abarth@webkit.org401a3792013-03-03 10:12:59 +000093#include "PolicyChecker.h"
andersca2b2c5ce2007-01-15 21:55:00 +000094#include "ProgressTracker.h"
beidson50c3bd82007-01-03 03:11:18 +000095#include "ResourceHandle.h"
beidson@apple.come3ea01d2015-07-02 18:33:23 +000096#include "ResourceLoadInfo.h"
darinc370e7e2006-11-08 05:52:27 +000097#include "ResourceRequest.h"
ossy@webkit.org66d8c0a2014-02-05 11:42:35 +000098#include "SVGDocument.h"
99#include "SVGLocatable.h"
100#include "SVGNames.h"
101#include "SVGPreserveAspectRatio.h"
ossy@webkit.org66d8c0a2014-02-05 11:42:35 +0000102#include "SVGViewElement.h"
103#include "SVGViewSpec.h"
beidson@apple.comc7fe45f2010-07-21 23:19:55 +0000104#include "SchemeRegistry.h"
weinig@apple.com79099002008-11-21 05:51:28 +0000105#include "ScriptController.h"
darin@chromium.org6b412472008-11-24 23:07:38 +0000106#include "ScriptSourceCode.h"
vsevik@chromium.org53bb0692012-01-18 20:59:10 +0000107#include "ScrollAnimator.h"
weinige06430a2007-10-19 20:53:22 +0000108#include "SecurityOrigin.h"
abarth@webkit.orgeea90662011-11-09 07:58:49 +0000109#include "SecurityPolicy.h"
darinc370e7e2006-11-08 05:52:27 +0000110#include "SegmentedString.h"
yurys@chromium.org832b9142010-08-05 12:36:31 +0000111#include "SerializedScriptValue.h"
darinc370e7e2006-11-08 05:52:27 +0000112#include "Settings.h"
akling@apple.com7f81b1e2013-09-06 17:23:03 +0000113#include "SubframeLoader.h"
darin@apple.com1b75e772010-06-15 22:20:34 +0000114#include "TextResourceDecoder.h"
beidson@apple.come3ea01d2015-07-02 18:33:23 +0000115#include "UserContentController.h"
darin@apple.com1b75e772010-06-15 22:20:34 +0000116#include "WindowFeatures.h"
117#include "XMLDocumentParser.h"
darin@apple.com1b75e772010-06-15 22:20:34 +0000118#include <wtf/CurrentTime.h>
akling@apple.comf8515982013-09-02 18:50:01 +0000119#include <wtf/Ref.h>
darin@apple.com1b75e772010-06-15 22:20:34 +0000120#include <wtf/StdLibExtras.h>
121#include <wtf/text/CString.h>
zimmermann@webkit.orgb5e11e62011-05-16 07:56:06 +0000122#include <wtf/text/WTFString.h>
darin@apple.com1b75e772010-06-15 22:20:34 +0000123
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +0000124#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
jeremy@chromium.orgc4b86e32011-02-13 20:28:39 +0000125#include "Archive.h"
jeremy@chromium.orgc4b86e32011-02-13 20:28:39 +0000126#endif
127
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000128#if PLATFORM(IOS)
129#include "DocumentType.h"
130#include "MemoryPressureHandler.h"
131#include "ResourceLoader.h"
132#include "RuntimeApplicationChecksIOS.h"
133#include "SystemMemory.h"
134#include "WKContentObservation.h"
135#endif
loislo@chromium.org82b9dde2012-09-12 13:16:31 +0000136
darinfa7a4e32006-10-30 00:37:02 +0000137namespace WebCore {
138
darin@apple.com1b75e772010-06-15 22:20:34 +0000139using namespace HTMLNames;
oliverb64e4082007-10-12 13:13:51 +0000140using namespace SVGNames;
darinc370e7e2006-11-08 05:52:27 +0000141
commit-queue@webkit.orgff400aa2011-03-10 23:43:48 +0000142static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
darinc370e7e2006-11-08 05:52:27 +0000143
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000144#if PLATFORM(IOS)
145const int memoryLevelThresholdToPrunePageCache = 20;
146#endif
147
darinc370e7e2006-11-08 05:52:27 +0000148bool isBackForwardLoadType(FrameLoadType type)
149{
150 switch (type) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +0000151 case FrameLoadType::Standard:
152 case FrameLoadType::Reload:
153 case FrameLoadType::ReloadFromOrigin:
154 case FrameLoadType::Same:
155 case FrameLoadType::RedirectWithLockedBackForwardList:
156 case FrameLoadType::Replace:
157 return false;
158 case FrameLoadType::Back:
159 case FrameLoadType::Forward:
160 case FrameLoadType::IndexedBackForward:
161 return true;
darinc370e7e2006-11-08 05:52:27 +0000162 }
163 ASSERT_NOT_REACHED();
164 return false;
165}
166
cjerdonek@webkit.org75d10692010-05-18 16:18:31 +0000167// This is not in the FrameLoader class to emphasize that it does not depend on
168// private FrameLoader data, and to avoid increasing the number of public functions
169// with access to private data. Since only this .cpp file needs it, making it
170// non-member lets us exclude it from the header file, thus keeping FrameLoader.h's
171// API simpler.
172//
cdumez@apple.comd6738dc2015-05-04 23:58:32 +0000173static bool isDocumentSandboxed(Frame& frame, SandboxFlags mask)
cjerdonek@webkit.org75d10692010-05-18 16:18:31 +0000174{
cdumez@apple.comd6738dc2015-05-04 23:58:32 +0000175 return frame.document() && frame.document()->isSandboxed(mask);
cjerdonek@webkit.org75d10692010-05-18 16:18:31 +0000176}
177
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +0000178struct ForbidPromptsScope {
179 ForbidPromptsScope(Page* page) : m_page(page)
180 {
181 if (!m_page)
182 return;
183 m_page->forbidPrompts();
184 }
185
186 ~ForbidPromptsScope()
187 {
188 if (!m_page)
189 return;
190 m_page->allowPrompts();
191 }
192
193 Page* m_page;
194};
195
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000196class FrameLoader::FrameProgressTracker {
197public:
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000198 explicit FrameProgressTracker(Frame& frame)
199 : m_frame(frame)
200 , m_inProgress(false)
201 {
202 }
203
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000204 ~FrameProgressTracker()
205 {
jpfau@apple.com7907c6b2014-10-28 22:38:44 +0000206 if (m_inProgress && m_frame.page())
andersca@apple.comcd088792014-01-10 07:19:29 +0000207 m_frame.page()->progress().progressCompleted(m_frame);
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000208 }
209
210 void progressStarted()
211 {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000212 ASSERT(m_frame.page());
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000213 if (!m_inProgress)
andersca@apple.comcd088792014-01-10 07:19:29 +0000214 m_frame.page()->progress().progressStarted(m_frame);
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000215 m_inProgress = true;
216 }
217
218 void progressCompleted()
219 {
220 ASSERT(m_inProgress);
akling@apple.com7f50aae2013-08-22 16:01:31 +0000221 ASSERT(m_frame.page());
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000222 m_inProgress = false;
andersca@apple.comcd088792014-01-10 07:19:29 +0000223 m_frame.page()->progress().progressCompleted(m_frame);
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000224 }
225
226private:
akling@apple.com7f50aae2013-08-22 16:01:31 +0000227 Frame& m_frame;
japhet@chromium.org7879dd72012-08-30 02:58:37 +0000228 bool m_inProgress;
229};
230
akling@apple.com7f50aae2013-08-22 16:01:31 +0000231FrameLoader::FrameLoader(Frame& frame, FrameLoaderClient& client)
darinfa7a4e32006-10-30 00:37:02 +0000232 : m_frame(frame)
ggaren1b09a122006-11-29 06:11:14 +0000233 , m_client(client)
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000234 , m_policyChecker(std::make_unique<PolicyChecker>(frame))
235 , m_history(std::make_unique<HistoryController>(frame))
akling@apple.com654fd9a2013-10-06 21:07:29 +0000236 , m_notifier(frame)
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000237 , m_subframeLoader(std::make_unique<SubframeLoader>(frame))
238 , m_icon(std::make_unique<IconController>(frame))
239 , m_mixedContentChecker(frame)
japhet@chromium.orgce6c1ba2012-11-28 19:30:48 +0000240 , m_state(FrameStateProvisional)
andersca@apple.comb50fcc32014-06-19 00:13:20 +0000241 , m_loadType(FrameLoadType::Standard)
darinfa7a4e32006-10-30 00:37:02 +0000242 , m_quickRedirectComing(false)
243 , m_sentRedirectNotification(false)
darinc370e7e2006-11-08 05:52:27 +0000244 , m_inStopAllLoaders(false)
darinc370e7e2006-11-08 05:52:27 +0000245 , m_isExecutingJavaScriptFormAction(false)
japhet@chromium.orgce6c1ba2012-11-28 19:30:48 +0000246 , m_didCallImplicitClose(true)
darinc370e7e2006-11-08 05:52:27 +0000247 , m_wasUnloadEventEmitted(false)
248 , m_isComplete(false)
darinc370e7e2006-11-08 05:52:27 +0000249 , m_needsClear(false)
andersca@apple.com574a7452014-11-21 20:10:13 +0000250 , m_checkTimer(*this, &FrameLoader::checkTimerFired)
darin@apple.comf53381b2009-09-23 23:27:01 +0000251 , m_shouldCallCheckCompleted(false)
252 , m_shouldCallCheckLoadComplete(false)
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000253 , m_opener(nullptr)
beidson@apple.comac095c02009-08-18 01:37:56 +0000254 , m_loadingFromCachedPage(false)
beidson@apple.com1390a812013-07-20 06:43:51 +0000255 , m_currentNavigationHasShownBeforeUnloadConfirmPanel(false)
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000256 , m_loadsSynchronously(false)
abarth@webkit.orgf2c54c22010-04-11 06:57:13 +0000257 , m_forcedSandboxFlags(SandboxNone)
darinfa7a4e32006-10-30 00:37:02 +0000258{
259}
260
261FrameLoader::~FrameLoader()
262{
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000263 setOpener(nullptr);
darinc370e7e2006-11-08 05:52:27 +0000264
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +0000265 for (auto& frame : m_openedFrames)
266 frame->loader().m_opener = nullptr;
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +0000267
akling@apple.com7f50aae2013-08-22 16:01:31 +0000268 m_client.frameLoaderDestroyed();
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +0000269
270 if (m_networkingContext)
271 m_networkingContext->invalidate();
darinfa7a4e32006-10-30 00:37:02 +0000272}
273
mrowe@apple.com5d92f2a2008-09-30 21:04:35 +0000274void FrameLoader::init()
mjs8d620d52007-05-10 12:31:42 +0000275{
darin@apple.com73006812011-06-29 20:46:33 +0000276 // This somewhat odd set of steps gives the frame an initial empty document.
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +0000277 setPolicyDocumentLoader(m_client.createDocumentLoader(ResourceRequest(URL(ParsedURLString, emptyString())), SubstituteData()).ptr());
mjs8d620d52007-05-10 12:31:42 +0000278 setProvisionalDocumentLoader(m_policyDocumentLoader.get());
japhet@chromium.orgce6c1ba2012-11-28 19:30:48 +0000279 m_provisionalDocumentLoader->startLoadingMainResource();
jpfau@apple.comec9eb512014-07-10 01:13:45 +0000280
281 Ref<Frame> protect(m_frame);
akling@apple.com7f50aae2013-08-22 16:01:31 +0000282 m_frame.document()->cancelParsing();
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000283 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +0000284
akling@apple.com7f50aae2013-08-22 16:01:31 +0000285 m_networkingContext = m_client.createNetworkingContext();
weinig@apple.comeefc25d2013-11-08 22:42:27 +0000286 m_progressTracker = std::make_unique<FrameProgressTracker>(m_frame);
mjs8d620d52007-05-10 12:31:42 +0000287}
288
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000289#if PLATFORM(IOS)
290void FrameLoader::initForSynthesizedDocument(const URL&)
291{
292 // FIXME: We need to initialize the document URL to the specified URL. Currently the URL is empty and hence
293 // FrameLoader::checkCompleted() will overwrite the URL of the document to be activeDocumentLoader()->documentURL().
294
295 RefPtr<DocumentLoader> loader = m_client.createDocumentLoader(ResourceRequest(URL(ParsedURLString, emptyString())), SubstituteData());
beidson@apple.com10a537f2015-07-09 22:30:42 +0000296 loader->attachToFrame(m_frame);
antti@apple.com7a96ae82014-09-04 20:59:43 +0000297 loader->setResponse(ResourceResponse(URL(), ASCIILiteral("text/html"), 0, String()));
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000298 loader->setCommitted(true);
299 setDocumentLoader(loader.get());
300
301 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
302 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
303 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
304 m_client.transitionToCommittedForNewPage();
305
306 m_didCallImplicitClose = true;
307 m_isComplete = true;
308 m_state = FrameStateComplete;
309 m_needsClear = true;
310
311 m_networkingContext = m_client.createNetworkingContext();
aestes@apple.com52fb6792014-03-01 05:14:42 +0000312 m_progressTracker = std::make_unique<FrameProgressTracker>(m_frame);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000313}
314#endif
315
darinfa7a4e32006-10-30 00:37:02 +0000316void FrameLoader::setDefersLoading(bool defers)
317{
darin8207db42007-02-20 18:18:39 +0000318 if (m_documentLoader)
319 m_documentLoader->setDefersLoading(defers);
320 if (m_provisionalDocumentLoader)
321 m_provisionalDocumentLoader->setDefersLoading(defers);
322 if (m_policyDocumentLoader)
323 m_policyDocumentLoader->setDefersLoading(defers);
akling@apple.com672cb852013-08-22 20:27:27 +0000324 history().setDefersLoading(defers);
darin@apple.comf53381b2009-09-23 23:27:01 +0000325
326 if (!defers) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000327 m_frame.navigationScheduler().startTimer();
darin@apple.comf53381b2009-09-23 23:27:01 +0000328 startCheckCompleteTimer();
329 }
darinfa7a4e32006-10-30 00:37:02 +0000330}
331
beidson@apple.comee119d42015-04-28 19:38:13 +0000332void FrameLoader::changeLocation(const FrameLoadRequest& request)
mjsd40bfee2007-07-09 06:29:48 +0000333{
beidson@apple.comee119d42015-04-28 19:38:13 +0000334 urlSelected(request, nullptr);
darinc370e7e2006-11-08 05:52:27 +0000335}
336
beidson@apple.com87dc6312015-06-02 18:43:13 +0000337void FrameLoader::urlSelected(const URL& url, const String& passedTarget, Event* triggeringEvent, LockHistory lockHistory, LockBackForwardList lockBackForwardList, ShouldSendReferrer shouldSendReferrer, ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy)
darinc370e7e2006-11-08 05:52:27 +0000338{
beidson@apple.comee119d42015-04-28 19:38:13 +0000339 NewFrameOpenerPolicy newFrameOpenerPolicy = shouldSendReferrer == NeverSendReferrer ? NewFrameOpenerPolicy::Suppress : NewFrameOpenerPolicy::Allow;
340
beidson@apple.com87dc6312015-06-02 18:43:13 +0000341 urlSelected(FrameLoadRequest(m_frame.document()->securityOrigin(), ResourceRequest(url), passedTarget, lockHistory, lockBackForwardList, shouldSendReferrer, AllowNavigationToInvalidURL::Yes, newFrameOpenerPolicy, DoNotReplaceDocumentIfJavaScriptURL, shouldOpenExternalURLsPolicy), triggeringEvent);
cjerdonek@webkit.org983777f2010-05-17 07:34:12 +0000342}
343
beidson@apple.comdab05722015-05-31 05:53:06 +0000344void FrameLoader::urlSelected(const FrameLoadRequest& passedRequest, Event* triggeringEvent)
cjerdonek@webkit.org983777f2010-05-17 07:34:12 +0000345{
akling@apple.comf8515982013-09-02 18:50:01 +0000346 Ref<Frame> protect(m_frame);
darin@apple.com1cf3d562010-12-07 16:23:03 +0000347 FrameLoadRequest frameRequest(passedRequest);
348
beidson@apple.comee119d42015-04-28 19:38:13 +0000349 if (m_frame.script().executeIfJavaScriptURL(frameRequest.resourceRequest().url(), frameRequest.shouldReplaceDocumentIfJavaScriptURL()))
weinig@apple.com6b00e242008-01-08 01:30:27 +0000350 return;
351
darin@apple.com1cf3d562010-12-07 16:23:03 +0000352 if (frameRequest.frameName().isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000353 frameRequest.setFrameName(m_frame.document()->baseTarget());
darinc370e7e2006-11-08 05:52:27 +0000354
darin@apple.com4cd1b242009-03-27 23:37:46 +0000355 addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
356
beidson@apple.comee119d42015-04-28 19:38:13 +0000357 loadFrameRequest(frameRequest, triggeringEvent, nullptr);
darinc370e7e2006-11-08 05:52:27 +0000358}
359
dglazkov@chromium.org25a57e52010-06-20 21:00:35 +0000360void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission)
darinc370e7e2006-11-08 05:52:27 +0000361{
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000362 ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod);
dglazkov@chromium.org25a57e52010-06-20 21:00:35 +0000363
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000364 // FIXME: Find a good spot for these.
365 ASSERT(submission->data());
366 ASSERT(submission->state());
akling@apple.com7f50aae2013-08-22 16:01:31 +0000367 ASSERT(!submission->state()->sourceDocument()->frame() || submission->state()->sourceDocument()->frame() == &m_frame);
beidson2b283222006-11-14 03:54:33 +0000368
akling@apple.com7f50aae2013-08-22 16:01:31 +0000369 if (!m_frame.page())
adele@apple.comf3d6b892008-04-29 01:30:20 +0000370 return;
371
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000372 if (submission->action().isEmpty())
darinc370e7e2006-11-08 05:52:27 +0000373 return;
374
cdumez@apple.comd6738dc2015-05-04 23:58:32 +0000375 if (isDocumentSandboxed(m_frame, SandboxForms)) {
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +0000376 // 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 +0000377 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 +0000378 return;
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +0000379 }
abarth@webkit.orgb8a10552009-12-02 02:40:35 +0000380
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000381 if (protocolIsJavaScript(submission->action())) {
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000382 if (!m_frame.document()->contentSecurityPolicy()->allowFormAction(URL(submission->action())))
commit-queue@webkit.org78e860e2012-08-16 12:42:09 +0000383 return;
darinc370e7e2006-11-08 05:52:27 +0000384 m_isExecutingJavaScriptFormAction = true;
ap@apple.come6afcb62014-04-20 19:02:13 +0000385 Ref<Frame> protect(m_frame);
akling@apple.com7f50aae2013-08-22 16:01:31 +0000386 m_frame.script().executeIfJavaScriptURL(submission->action(), DoNotReplaceDocumentIfJavaScriptURL);
darinc370e7e2006-11-08 05:52:27 +0000387 m_isExecutingJavaScriptFormAction = false;
388 return;
389 }
390
abarth@webkit.org5d82cdb2012-04-13 07:53:46 +0000391 Frame* targetFrame = findFrameForNavigation(submission->target(), submission->state()->sourceDocument());
darin@apple.com0f88bda2009-04-02 00:30:50 +0000392 if (!targetFrame) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000393 if (!DOMWindow::allowPopUp(&m_frame) && !ScriptController::processingUserGesture())
abarth@webkit.orgc72185c2010-04-09 06:43:19 +0000394 return;
395
ap@apple.comf8c414e2013-08-13 03:44:57 +0000396 // FIXME: targetFrame can be 0 for two distinct reasons:
397 // 1. The frame was not found by name, so we should try opening a new window.
398 // 2. The frame was found, but navigating it was not allowed, e.g. by HTML5 sandbox or by origin checks.
399 // Continuing form submission makes no sense in the latter case.
400 // There is a repeat check after timer fires, so this is not a correctness issue.
401
akling@apple.com7f50aae2013-08-22 16:01:31 +0000402 targetFrame = &m_frame;
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000403 } else
404 submission->clearTarget();
405
darin@apple.com0f88bda2009-04-02 00:30:50 +0000406 if (!targetFrame->page())
darinc370e7e2006-11-08 05:52:27 +0000407 return;
darin@apple.com0f88bda2009-04-02 00:30:50 +0000408
409 // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
410
411 // We do not want to submit more than one form from the same page, nor do we want to submit a single
412 // form more than once. This flag prevents these from happening; not sure how other browsers prevent this.
413 // The flag is reset in each time we start handle a new mouse or key down event, and
414 // also in setView since this part may get reused for a page from the back/forward cache.
415 // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
416
417 // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
418 // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
419 // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
420
darin@apple.comfed4d162013-08-25 02:28:06 +0000421 if (m_frame.tree().isDescendantOf(targetFrame)) {
commit-queue@webkit.org43964052012-08-13 19:30:15 +0000422 if (m_submittedFormURL == submission->requestURL())
darin@apple.com0f88bda2009-04-02 00:30:50 +0000423 return;
commit-queue@webkit.org43964052012-08-13 19:30:15 +0000424 m_submittedFormURL = submission->requestURL();
darinc370e7e2006-11-08 05:52:27 +0000425 }
426
akling@apple.com7f50aae2013-08-22 16:01:31 +0000427 submission->data()->generateFiles(m_frame.document());
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +0000428 submission->setReferrer(outgoingReferrer());
dglazkov@chromium.org996fc222010-06-21 16:36:40 +0000429 submission->setOrigin(outgoingOrigin());
darinc370e7e2006-11-08 05:52:27 +0000430
akling@apple.com9ce995f2013-08-21 20:54:20 +0000431 targetFrame->navigationScheduler().scheduleFormSubmission(submission);
darinc370e7e2006-11-08 05:52:27 +0000432}
433
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +0000434void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
darinc370e7e2006-11-08 05:52:27 +0000435{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000436 if (m_frame.document() && m_frame.document()->parser())
437 m_frame.document()->parser()->stopParsing();
mjs8d620d52007-05-10 12:31:42 +0000438
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +0000439 if (unloadEventPolicy != UnloadEventPolicyNone)
440 handleUnloadEvents(unloadEventPolicy);
darinc370e7e2006-11-08 05:52:27 +0000441
darin@apple.com4d9d7182009-09-23 00:38:04 +0000442 m_isComplete = true; // to avoid calling completed() in finishedParsing()
ggarena57755c2007-07-09 21:08:10 +0000443 m_didCallImplicitClose = true; // don't want that one either
darinc370e7e2006-11-08 05:52:27 +0000444
akling@apple.com7f50aae2013-08-22 16:01:31 +0000445 if (m_frame.document() && m_frame.document()->parsing()) {
darinc370e7e2006-11-08 05:52:27 +0000446 finishedParsing();
akling@apple.com7f50aae2013-08-22 16:01:31 +0000447 m_frame.document()->setParsing(false);
darinc370e7e2006-11-08 05:52:27 +0000448 }
abarth@webkit.org55d49da2011-06-20 23:32:54 +0000449
akling@apple.com7f50aae2013-08-22 16:01:31 +0000450 if (Document* doc = m_frame.document()) {
tonyg@chromium.orgd299d8a72010-09-06 18:32:48 +0000451 // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior.
452 // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537
453 doc->setReadyState(Document::Complete);
454
mark.lam@apple.com45beb072012-12-12 23:04:20 +0000455 // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here?
cdumez@apple.com0fb69f02015-02-26 23:22:17 +0000456 DatabaseManager::singleton().stopDatabases(doc, 0);
darinc370e7e2006-11-08 05:52:27 +0000457 }
458
ap@apple.com3f0a0a12010-06-24 23:58:36 +0000459 // 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 +0000460 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +0000461}
462
463void FrameLoader::stop()
464{
465 // http://bugs.webkit.org/show_bug.cgi?id=10854
466 // The frame's last ref may be removed and it will be deleted by checkCompleted().
akling@apple.comf8515982013-09-02 18:50:01 +0000467 Ref<Frame> protect(m_frame);
abarth@webkit.orgfd912902011-06-10 21:16:20 +0000468
akling@apple.com7f50aae2013-08-22 16:01:31 +0000469 if (DocumentParser* parser = m_frame.document()->parser()) {
abarth@webkit.orgfd912902011-06-10 21:16:20 +0000470 parser->stopParsing();
471 parser->finish();
472 }
abarth@webkit.org4e009972011-06-13 20:36:03 +0000473
akling@apple.comf7219112013-09-08 10:54:53 +0000474 icon().stopLoader();
darinc370e7e2006-11-08 05:52:27 +0000475}
476
ap@apple.come042b632013-05-17 20:04:43 +0000477void FrameLoader::willTransitionToCommitted()
478{
479 // This function is called when a frame is still fully in place (not cached, not detached), but will be replaced.
480
akling@apple.com7f50aae2013-08-22 16:01:31 +0000481 if (m_frame.editor().hasComposition()) {
ap@apple.come042b632013-05-17 20:04:43 +0000482 // The text was already present in DOM, so it's better to confirm than to cancel the composition.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000483 m_frame.editor().confirmComposition();
ap@apple.comc9851362014-12-11 17:23:34 +0000484 if (EditorClient* editorClient = m_frame.editor().client()) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000485 editorClient->respondToChangedSelection(&m_frame);
ap@apple.comc9851362014-12-11 17:23:34 +0000486 editorClient->discardedComposition(&m_frame);
487 }
ap@apple.come042b632013-05-17 20:04:43 +0000488 }
489}
490
darinc370e7e2006-11-08 05:52:27 +0000491bool FrameLoader::closeURL()
492{
akling@apple.com672cb852013-08-22 20:27:27 +0000493 history().saveDocumentState();
stavila@adobe.comeb50d7c2014-12-17 10:14:32 +0000494
akling@apple.com7f50aae2013-08-22 16:01:31 +0000495 Document* currentDocument = m_frame.document();
stavila@adobe.comeb50d7c2014-12-17 10:14:32 +0000496 UnloadEventPolicy unloadEventPolicy;
497 if (m_frame.page() && m_frame.page()->chrome().client().isSVGImageChromeClient()) {
498 // If this is the SVGDocument of an SVGImage, no need to dispatch events or recalcStyle.
499 unloadEventPolicy = UnloadEventPolicyNone;
500 } else {
501 // Should only send the pagehide event here if the current document exists and has not been placed in the page cache.
502 unloadEventPolicy = currentDocument && !currentDocument->inPageCache() ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly;
503 }
504
505 stopLoading(unloadEventPolicy);
beidson@apple.com212b7842009-09-03 00:55:18 +0000506
akling@apple.com7f50aae2013-08-22 16:01:31 +0000507 m_frame.editor().clearUndoRedoOperations();
darinc370e7e2006-11-08 05:52:27 +0000508 return true;
509}
510
abarth@webkit.org55d49da2011-06-20 23:32:54 +0000511bool FrameLoader::didOpenURL()
darinc370e7e2006-11-08 05:52:27 +0000512{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000513 if (m_frame.navigationScheduler().redirectScheduledDuringLoad()) {
darinc370e7e2006-11-08 05:52:27 +0000514 // A redirect was scheduled before the document was created.
515 // This can happen when one frame changes another frame's location.
516 return false;
darin@apple.com0f88bda2009-04-02 00:30:50 +0000517 }
darinc370e7e2006-11-08 05:52:27 +0000518
akling@apple.com7f50aae2013-08-22 16:01:31 +0000519 m_frame.navigationScheduler().cancel();
520 m_frame.editor().clearLastEditCommand();
darinc370e7e2006-11-08 05:52:27 +0000521
522 m_isComplete = false;
ggarena57755c2007-07-09 21:08:10 +0000523 m_didCallImplicitClose = false;
darinc370e7e2006-11-08 05:52:27 +0000524
ap@webkit.orgfbfb0f92009-05-08 07:58:08 +0000525 // If we are still in the process of initializing an empty document then
526 // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
527 // since it may cause clients to attempt to render the frame.
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000528 if (!m_stateMachine.creatingInitialEmptyDocument()) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000529 DOMWindow* window = m_frame.document()->domWindow();
abarth@webkit.org13fe1e22012-08-16 22:29:48 +0000530 window->setStatus(String());
531 window->setDefaultStatus(String());
ap@webkit.orgfbfb0f92009-05-08 07:58:08 +0000532 }
darinc370e7e2006-11-08 05:52:27 +0000533
534 started();
535
536 return true;
537}
538
ap@webkit.orga0a19872008-02-05 09:34:18 +0000539void FrameLoader::didExplicitOpen()
darinc370e7e2006-11-08 05:52:27 +0000540{
541 m_isComplete = false;
ggarena57755c2007-07-09 21:08:10 +0000542 m_didCallImplicitClose = false;
darinc370e7e2006-11-08 05:52:27 +0000543
andersca@apple.com1752dba2007-12-14 22:06:50 +0000544 // Calling document.open counts as committing the first real document load.
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000545 if (!m_stateMachine.committedFirstRealDocumentLoad())
546 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
andersca@apple.com1752dba2007-12-14 22:06:50 +0000547
darinc370e7e2006-11-08 05:52:27 +0000548 // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
549 // from a subsequent window.document.open / window.document.write call.
dbates@webkit.orgef42d382010-01-25 19:20:06 +0000550 // Canceling redirection here works for all cases because document.open
darinc370e7e2006-11-08 05:52:27 +0000551 // implicitly precedes document.write.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000552 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +0000553}
554
darinc370e7e2006-11-08 05:52:27 +0000555
556void FrameLoader::cancelAndClear()
557{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000558 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +0000559
560 if (!m_isComplete)
561 closeURL();
562
akling@apple.com7f50aae2013-08-22 16:01:31 +0000563 clear(m_frame.document(), false);
564 m_frame.script().updatePlatformScriptObjects();
darinc370e7e2006-11-08 05:52:27 +0000565}
566
abarth@webkit.org23ea90a2012-08-14 19:47:59 +0000567void FrameLoader::clear(Document* newDocument, bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView)
darinc370e7e2006-11-08 05:52:27 +0000568{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000569 m_frame.editor().clear();
darinc370e7e2006-11-08 05:52:27 +0000570
571 if (!m_needsClear)
572 return;
573 m_needsClear = false;
larsb6326762007-01-11 12:34:26 +0000574
akling@apple.com7f50aae2013-08-22 16:01:31 +0000575 if (!m_frame.document()->inPageCache()) {
576 m_frame.document()->cancelParsing();
577 m_frame.document()->stopActiveDOMObjects();
timothy_horton@apple.com70d58d82014-07-26 18:45:04 +0000578 bool hadLivingRenderTree = m_frame.document()->hasLivingRenderTree();
579 m_frame.document()->prepareForDestruction();
580 if (hadLivingRenderTree)
akling@apple.com7f50aae2013-08-22 16:01:31 +0000581 m_frame.document()->removeFocusedNodeOfSubtree(m_frame.document());
darinc370e7e2006-11-08 05:52:27 +0000582 }
583
584 // Do this after detaching the document so that the unload event works.
thatchera1e24df2007-09-14 23:53:29 +0000585 if (clearWindowProperties) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000586 InspectorInstrumentation::frameWindowDiscarded(&m_frame, m_frame.document()->domWindow());
587 m_frame.document()->domWindow()->resetUnlessSuspendedForPageCache();
588 m_frame.script().clearWindowShell(newDocument->domWindow(), m_frame.document()->inPageCache());
weinigf9307632007-07-18 05:40:54 +0000589 }
darinc370e7e2006-11-08 05:52:27 +0000590
akling@apple.com7f50aae2013-08-22 16:01:31 +0000591 m_frame.selection().prepareForDestruction();
592 m_frame.eventHandler().clear();
593 if (clearFrameView && m_frame.view())
594 m_frame.view()->clear();
eric@webkit.org0683d942008-08-06 10:01:35 +0000595
eric@webkit.org0683d942008-08-06 10:01:35 +0000596 // Do not drop the document before the ScriptController and view are cleared
597 // as some destructors might still try to access the document.
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +0000598 m_frame.setDocument(nullptr);
darinc370e7e2006-11-08 05:52:27 +0000599
akling@apple.com7f81b1e2013-09-06 17:23:03 +0000600 subframeLoader().clear();
eric@webkit.org0683d942008-08-06 10:01:35 +0000601
antti90500a32007-09-27 23:56:17 +0000602 if (clearScriptObjects)
akling@apple.com7f50aae2013-08-22 16:01:31 +0000603 m_frame.script().clearScriptObjects();
eric@webkit.org0683d942008-08-06 10:01:35 +0000604
akling@apple.com7f50aae2013-08-22 16:01:31 +0000605 m_frame.script().enableEval();
abarth@webkit.org9d220b62012-06-09 19:35:02 +0000606
akling@apple.com7f50aae2013-08-22 16:01:31 +0000607 m_frame.navigationScheduler().clear();
darinc370e7e2006-11-08 05:52:27 +0000608
darin@apple.comf53381b2009-09-23 23:27:01 +0000609 m_checkTimer.stop();
610 m_shouldCallCheckCompleted = false;
611 m_shouldCallCheckLoadComplete = false;
abarth@webkit.org91289c32010-04-12 04:54:55 +0000612
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000613 if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad())
614 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
darinc370e7e2006-11-08 05:52:27 +0000615}
616
617void FrameLoader::receivedFirstData()
618{
jcivelli@chromium.org4b94add2011-11-19 08:45:01 +0000619 dispatchDidCommitLoad();
620 dispatchDidClearWindowObjectsInAllWorlds();
beidson@apple.com2a75a962012-04-24 18:12:55 +0000621 dispatchGlobalObjectAvailableInAllWorlds();
jcivelli@chromium.org4b94add2011-11-19 08:45:01 +0000622
pkasting@chromium.orgc733b942009-05-05 19:19:23 +0000623 if (m_documentLoader) {
evan@chromium.orgc3532e92011-03-31 15:17:13 +0000624 StringWithDirection ptitle = m_documentLoader->title();
pkasting@chromium.orgc733b942009-05-05 19:19:23 +0000625 // If we have a title let the WebView know about it.
626 if (!ptitle.isNull())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000627 m_client.dispatchDidReceiveTitle(ptitle);
pkasting@chromium.orgc733b942009-05-05 19:19:23 +0000628 }
darinc370e7e2006-11-08 05:52:27 +0000629
darin8207db42007-02-20 18:18:39 +0000630 if (!m_documentLoader)
631 return;
abarth@webkit.org55d49da2011-06-20 23:32:54 +0000632
633 double delay;
darin@apple.com47a20cb2014-04-27 16:06:27 +0000634 String urlString;
andersca@apple.com30391b42014-06-16 19:26:49 +0000635 if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField(HTTPHeaderName::Refresh), false, delay, urlString))
ape9991d52006-12-08 18:19:51 +0000636 return;
darin@apple.com47a20cb2014-04-27 16:06:27 +0000637 URL completedURL;
638 if (urlString.isEmpty())
639 completedURL = m_frame.document()->url();
ape9991d52006-12-08 18:19:51 +0000640 else
darin@apple.com47a20cb2014-04-27 16:06:27 +0000641 completedURL = m_frame.document()->completeURL(urlString);
darinebefc172006-11-08 09:48:44 +0000642
darin@apple.com47a20cb2014-04-27 16:06:27 +0000643 if (!protocolIsJavaScript(completedURL))
beidson@apple.com87dc6312015-06-02 18:43:13 +0000644 m_frame.navigationScheduler().scheduleRedirect(m_frame.document(), delay, completedURL);
ddkilzer@apple.com70f15392014-04-01 19:21:34 +0000645 else {
646 String message = "Refused to refresh " + m_frame.document()->url().stringCenterEllipsizedToLength() + " to a javascript: URL";
647 m_frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, message);
648 }
darinc370e7e2006-11-08 05:52:27 +0000649}
650
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000651void FrameLoader::setOutgoingReferrer(const URL& url)
japhet@chromium.orgb254c9b2011-01-26 19:14:26 +0000652{
levin@chromium.org1a2fef42011-03-01 02:10:28 +0000653 m_outgoingReferrer = url.strippedForUseAsReferrer();
abarth@webkit.org412c54e2010-04-20 22:12:16 +0000654}
abarth@webkit.org91289c32010-04-12 04:54:55 +0000655
abarth@webkit.org412c54e2010-04-20 22:12:16 +0000656void FrameLoader::didBeginDocument(bool dispatch)
657{
658 m_needsClear = true;
659 m_isComplete = false;
660 m_didCallImplicitClose = false;
akling@apple.com7f50aae2013-08-22 16:01:31 +0000661 m_frame.document()->setReadyState(Document::Loading);
abarth@webkit.org91289c32010-04-12 04:54:55 +0000662
663 if (m_pendingStateObject) {
akling@apple.com7f50aae2013-08-22 16:01:31 +0000664 m_frame.document()->statePopped(m_pendingStateObject.get());
cdumez@apple.comd839ea12015-07-04 19:42:18 +0000665 m_pendingStateObject = nullptr;
abarth@webkit.org91289c32010-04-12 04:54:55 +0000666 }
abarth@webkit.org91289c32010-04-12 04:54:55 +0000667
andersca@apple.com6c6fb4b2009-08-12 22:03:02 +0000668 if (dispatch)
aroben@apple.com11dd5262009-11-13 23:49:05 +0000669 dispatchDidClearWindowObjectsInAllWorlds();
abarth@webkit.org412c54e2010-04-20 22:12:16 +0000670
abarth@webkit.org622d9df2009-05-22 16:44:47 +0000671 updateFirstPartyForCookies();
akling@apple.com7f50aae2013-08-22 16:01:31 +0000672 m_frame.document()->initContentSecurityPolicy();
darinc370e7e2006-11-08 05:52:27 +0000673
akling@apple.com1c29edbc2013-08-23 23:19:21 +0000674 const Settings& settings = m_frame.settings();
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +0000675 m_frame.document()->cachedResourceLoader().setImagesEnabled(settings.areImagesEnabled());
676 m_frame.document()->cachedResourceLoader().setAutoLoadImages(settings.loadsImagesAutomatically());
aroben@apple.com3adf2452008-02-07 23:19:31 +0000677
collinj@webkit.org9c672f62008-09-19 04:15:14 +0000678 if (m_documentLoader) {
andersca@apple.com30391b42014-06-16 19:26:49 +0000679 String dnsPrefetchControl = m_documentLoader->response().httpHeaderField(HTTPHeaderName::XDNSPrefetchControl);
collinj@webkit.org9c672f62008-09-19 04:15:14 +0000680 if (!dnsPrefetchControl.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000681 m_frame.document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
jochen@chromium.orgadec40f2011-02-09 17:03:38 +0000682
andersca@apple.com30391b42014-06-16 19:26:49 +0000683 String policyValue = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ContentSecurityPolicy);
mkwst@chromium.orga9bf73d2012-10-31 23:41:27 +0000684 if (!policyValue.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000685 m_frame.document()->contentSecurityPolicy()->didReceiveHeader(policyValue, ContentSecurityPolicy::Enforce);
abarth@webkit.orgbd0c7752011-05-07 02:13:06 +0000686
andersca@apple.com30391b42014-06-16 19:26:49 +0000687 policyValue = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ContentSecurityPolicyReportOnly);
mkwst@chromium.orga9bf73d2012-10-31 23:41:27 +0000688 if (!policyValue.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000689 m_frame.document()->contentSecurityPolicy()->didReceiveHeader(policyValue, ContentSecurityPolicy::Report);
mkwst@chromium.orga9bf73d2012-10-31 23:41:27 +0000690
andersca@apple.com30391b42014-06-16 19:26:49 +0000691 policyValue = m_documentLoader->response().httpHeaderField(HTTPHeaderName::XWebKitCSP);
mkwst@chromium.orga9bf73d2012-10-31 23:41:27 +0000692 if (!policyValue.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000693 m_frame.document()->contentSecurityPolicy()->didReceiveHeader(policyValue, ContentSecurityPolicy::PrefixedEnforce);
mkwst@chromium.orga9bf73d2012-10-31 23:41:27 +0000694
andersca@apple.com30391b42014-06-16 19:26:49 +0000695 policyValue = m_documentLoader->response().httpHeaderField(HTTPHeaderName::XWebKitCSPReportOnly);
mkwst@chromium.orga9bf73d2012-10-31 23:41:27 +0000696 if (!policyValue.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000697 m_frame.document()->contentSecurityPolicy()->didReceiveHeader(policyValue, ContentSecurityPolicy::PrefixedReport);
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +0000698
andersca@apple.com30391b42014-06-16 19:26:49 +0000699 String headerContentLanguage = m_documentLoader->response().httpHeaderField(HTTPHeaderName::ContentLanguage);
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +0000700 if (!headerContentLanguage.isEmpty()) {
701 size_t commaIndex = headerContentLanguage.find(',');
702 headerContentLanguage.truncate(commaIndex); // notFound == -1 == don't truncate
703 headerContentLanguage = headerContentLanguage.stripWhiteSpace(isHTMLSpace);
704 if (!headerContentLanguage.isEmpty())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000705 m_frame.document()->setContentLanguage(headerContentLanguage);
commit-queue@webkit.org26a3a092012-10-18 19:53:58 +0000706 }
collinj@webkit.org9c672f62008-09-19 04:15:14 +0000707 }
708
akling@apple.com672cb852013-08-22 20:27:27 +0000709 history().restoreDocumentState();
darinc370e7e2006-11-08 05:52:27 +0000710}
711
darinc370e7e2006-11-08 05:52:27 +0000712void FrameLoader::finishedParsing()
713{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000714 m_frame.injectUserScripts(InjectAtDocumentEnd);
aestes@apple.come35644e2011-04-07 20:23:48 +0000715
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000716 if (m_stateMachine.creatingInitialEmptyDocument())
mjs8d620d52007-05-10 12:31:42 +0000717 return;
718
darinc370e7e2006-11-08 05:52:27 +0000719 // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
720 // 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 +0000721 // Null-checking the FrameView indicates whether or not we're in the destructor.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000722 RefPtr<Frame> protector = m_frame.view() ? &m_frame : 0;
darinc370e7e2006-11-08 05:52:27 +0000723
akling@apple.com7f50aae2013-08-22 16:01:31 +0000724 m_client.dispatchDidFinishDocumentLoad();
darin@chromium.org1750e242008-12-08 18:13:25 +0000725
cdumez@apple.com6d7c65e2015-09-02 17:07:57 +0000726 scrollToFragmentWithParentBoundary(m_frame.document()->url());
727
darinc370e7e2006-11-08 05:52:27 +0000728 checkCompleted();
729
akling@apple.com7f50aae2013-08-22 16:01:31 +0000730 if (!m_frame.view())
darinc370e7e2006-11-08 05:52:27 +0000731 return; // We are being destroyed by something checkCompleted called.
732
733 // Check if the scrollbars are really needed for the content.
734 // If not, remove them, relayout, and repaint.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000735 m_frame.view()->restoreScrollbar();
darinc370e7e2006-11-08 05:52:27 +0000736}
737
738void FrameLoader::loadDone()
739{
ap@webkit.orgf9b6eff2009-02-10 17:33:33 +0000740 checkCompleted();
darinc370e7e2006-11-08 05:52:27 +0000741}
742
darin@apple.com4d9d7182009-09-23 00:38:04 +0000743bool FrameLoader::allChildrenAreComplete() const
744{
darin@apple.comfed4d162013-08-25 02:28:06 +0000745 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling()) {
andersca@apple.comdf550b92013-08-15 22:17:17 +0000746 if (!child->loader().m_isComplete)
darin@apple.com4d9d7182009-09-23 00:38:04 +0000747 return false;
748 }
749 return true;
750}
751
darin@apple.comf53381b2009-09-23 23:27:01 +0000752bool FrameLoader::allAncestorsAreComplete() const
753{
darin@apple.comfed4d162013-08-25 02:28:06 +0000754 for (Frame* ancestor = &m_frame; ancestor; ancestor = ancestor->tree().parent()) {
andersca@apple.comdf550b92013-08-15 22:17:17 +0000755 if (!ancestor->loader().m_isComplete)
darin@apple.comf53381b2009-09-23 23:27:01 +0000756 return false;
757 }
758 return true;
759}
760
darinc370e7e2006-11-08 05:52:27 +0000761void FrameLoader::checkCompleted()
762{
darin@apple.comf53381b2009-09-23 23:27:01 +0000763 m_shouldCallCheckCompleted = false;
764
darinc370e7e2006-11-08 05:52:27 +0000765 // Have we completed before?
766 if (m_isComplete)
767 return;
768
769 // Are we still parsing?
akling@apple.com7f50aae2013-08-22 16:01:31 +0000770 if (m_frame.document()->parsing())
darinc370e7e2006-11-08 05:52:27 +0000771 return;
772
773 // Still waiting for images/scripts?
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +0000774 if (m_frame.document()->cachedResourceLoader().requestCount())
ap@webkit.orgf9b6eff2009-02-10 17:33:33 +0000775 return;
darinc370e7e2006-11-08 05:52:27 +0000776
eric.carlson@apple.com9c7fc722010-08-26 16:45:43 +0000777 // Still waiting for elements that don't go through a FrameLoader?
akling@apple.com7f50aae2013-08-22 16:01:31 +0000778 if (m_frame.document()->isDelayingLoadEvent())
eric.carlson@apple.com9c7fc722010-08-26 16:45:43 +0000779 return;
780
andreas.kling@nokia.com01f92442011-02-28 13:46:06 +0000781 // Any frame that hasn't completed yet?
782 if (!allChildrenAreComplete())
783 return;
784
darin@apple.comc2843002014-04-25 06:01:34 +0000785 // Important not to protect earlier in this function, because earlier parts
darin@apple.comfe9effd2014-04-25 06:02:42 +0000786 // of this function can be called in the frame's destructor, and it's not legal
darin@apple.comc2843002014-04-25 06:01:34 +0000787 // to ref an object while it's being destroyed.
788 Ref<Frame> protect(m_frame);
789
darinc370e7e2006-11-08 05:52:27 +0000790 // OK, completed.
791 m_isComplete = true;
cdumez@apple.comd839ea12015-07-04 19:42:18 +0000792 m_requestedHistoryItem = nullptr;
akling@apple.com7f50aae2013-08-22 16:01:31 +0000793 m_frame.document()->setReadyState(Document::Complete);
darinc370e7e2006-11-08 05:52:27 +0000794
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +0000795#if PLATFORM(IOS)
796 if (m_frame.document()->url().isEmpty()) {
797 // We need to update the document URL of a PDF document to be non-empty so that both back/forward history navigation
798 // between PDF pages and fragment navigation works. See <rdar://problem/9544769> for more details.
799 // FIXME: Is there a better place for this code, say DocumentLoader? Also, we should explicitly only update the URL
800 // of the document when it's a PDFDocument object instead of assuming that a Document object with an empty URL is a PDFDocument.
801 // FIXME: This code is incorrect for a synthesized document (which also has an empty URL). The URL for a synthesized
802 // document should be the URL specified to FrameLoader::initForSynthesizedDocument().
803 m_frame.document()->setURL(activeDocumentLoader()->documentURL());
804 }
805#endif
806
ggarena57755c2007-07-09 21:08:10 +0000807 checkCallImplicitClose(); // if we didn't do it before
darinc370e7e2006-11-08 05:52:27 +0000808
akling@apple.com7f50aae2013-08-22 16:01:31 +0000809 m_frame.navigationScheduler().startTimer();
darinc370e7e2006-11-08 05:52:27 +0000810
811 completed();
akling@apple.com7f50aae2013-08-22 16:01:31 +0000812 if (m_frame.page())
mjs8d620d52007-05-10 12:31:42 +0000813 checkLoadComplete();
darinc370e7e2006-11-08 05:52:27 +0000814}
815
andersca@apple.com574a7452014-11-21 20:10:13 +0000816void FrameLoader::checkTimerFired()
weinigc34c71c2007-03-09 16:05:37 +0000817{
akling@apple.comf8515982013-09-02 18:50:01 +0000818 Ref<Frame> protect(m_frame);
commit-queue@webkit.org667ee8b2012-02-08 02:21:04 +0000819
akling@apple.com7f50aae2013-08-22 16:01:31 +0000820 if (Page* page = m_frame.page()) {
darin@apple.comf53381b2009-09-23 23:27:01 +0000821 if (page->defersLoading())
822 return;
823 }
824 if (m_shouldCallCheckCompleted)
825 checkCompleted();
826 if (m_shouldCallCheckLoadComplete)
827 checkLoadComplete();
828}
829
830void FrameLoader::startCheckCompleteTimer()
831{
832 if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
833 return;
834 if (m_checkTimer.isActive())
835 return;
836 m_checkTimer.startOneShot(0);
weinigc34c71c2007-03-09 16:05:37 +0000837}
838
839void FrameLoader::scheduleCheckCompleted()
840{
darin@apple.comf53381b2009-09-23 23:27:01 +0000841 m_shouldCallCheckCompleted = true;
842 startCheckCompleteTimer();
beidson398923b2007-07-31 20:29:02 +0000843}
844
845void FrameLoader::scheduleCheckLoadComplete()
846{
darin@apple.comf53381b2009-09-23 23:27:01 +0000847 m_shouldCallCheckLoadComplete = true;
848 startCheckCompleteTimer();
beidson398923b2007-07-31 20:29:02 +0000849}
850
ggarena57755c2007-07-09 21:08:10 +0000851void FrameLoader::checkCallImplicitClose()
darinc370e7e2006-11-08 05:52:27 +0000852{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000853 if (m_didCallImplicitClose || m_frame.document()->parsing() || m_frame.document()->isDelayingLoadEvent())
darinc370e7e2006-11-08 05:52:27 +0000854 return;
855
darin@apple.com4d9d7182009-09-23 00:38:04 +0000856 if (!allChildrenAreComplete())
857 return; // still got a frame running -> too early
darinc370e7e2006-11-08 05:52:27 +0000858
ggarena57755c2007-07-09 21:08:10 +0000859 m_didCallImplicitClose = true;
darinc370e7e2006-11-08 05:52:27 +0000860 m_wasUnloadEventEmitted = false;
akling@apple.com7f50aae2013-08-22 16:01:31 +0000861 m_frame.document()->implicitClose();
darinc370e7e2006-11-08 05:52:27 +0000862}
863
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000864void FrameLoader::loadURLIntoChildFrame(const URL& url, const String& referer, Frame* childFrame)
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000865{
866 ASSERT(childFrame);
darin@apple.coma7e141f2009-03-06 17:22:07 +0000867
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +0000868#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
darin@apple.comfed4d162013-08-25 02:28:06 +0000869 RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree().uniqueName(), url);
mihaip@chromium.orge5dbd372010-12-08 02:32:41 +0000870 if (subframeArchive) {
andersca@apple.comdf550b92013-08-15 22:17:17 +0000871 childFrame->loader().loadArchive(subframeArchive.release());
mihaip@chromium.orge5dbd372010-12-08 02:32:41 +0000872 return;
873 }
jeremy@chromium.orgc4b86e32011-02-13 20:28:39 +0000874#endif // ENABLE(WEB_ARCHIVE)
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000875
akling@apple.com672cb852013-08-22 20:27:27 +0000876 HistoryItem* parentItem = history().currentItem();
darin@apple.coma7e141f2009-03-06 17:22:07 +0000877 // If we're moving in the back/forward list, we might want to replace the content
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000878 // of this child frame with whatever was there at that point.
japhet@chromium.org88c4b2b2011-07-22 19:01:56 +0000879 if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType())
akling@apple.com7f50aae2013-08-22 16:01:31 +0000880 && !m_frame.document()->loadEventFinished()) {
darin@apple.comfed4d162013-08-25 02:28:06 +0000881 HistoryItem* childItem = parentItem->childItemWithTarget(childFrame->tree().uniqueName());
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000882 if (childItem) {
ap@apple.com4d286a92013-08-19 23:41:18 +0000883 childFrame->loader().m_requestedHistoryItem = childItem;
cdumez@apple.com67e10f72015-01-29 18:38:51 +0000884 childFrame->loader().loadDifferentDocumentItem(*childItem, loadType(), MayAttemptCacheOnlyLoadForFormSubmissionItem);
mihaip@chromium.orge5dbd372010-12-08 02:32:41 +0000885 return;
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000886 }
887 }
888
beidson@apple.com87dc6312015-06-02 18:43:13 +0000889 FrameLoadRequest frameLoadRequest(m_frame.document()->securityOrigin(), ResourceRequest(url), "_self", LockHistory::No, LockBackForwardList::Yes, ShouldSendReferrer::MaybeSendReferrer, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress, ReplaceDocumentIfJavaScriptURL, ShouldOpenExternalURLsPolicy::ShouldNotAllow);
beidson@apple.com47ef96f2015-05-29 16:38:13 +0000890 childFrame->loader().loadURL(frameLoadRequest, referer, FrameLoadType::RedirectWithLockedBackForwardList, 0, 0);
891}
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000892
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +0000893#if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
894void FrameLoader::loadArchive(PassRefPtr<Archive> archive)
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000895{
japhet@chromium.orgac5cd4b2012-04-12 19:27:28 +0000896 ArchiveResource* mainResource = archive->mainResource();
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000897 ASSERT(mainResource);
898 if (!mainResource)
899 return;
beidson@apple.comceb7cba2015-05-19 22:22:51 +0000900
901 ResourceResponse response(URL(), mainResource->mimeType(), mainResource->data()->size(), mainResource->textEncoding());
902 SubstituteData substituteData(mainResource->data(), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000903
904 ResourceRequest request(mainResource->url());
mitz@apple.com630ef442014-02-19 08:12:24 +0000905#if PLATFORM(MAC)
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000906 request.applyWebArchiveHackForMail();
907#endif
908
akling@apple.com7f50aae2013-08-22 16:01:31 +0000909 RefPtr<DocumentLoader> documentLoader = m_client.createDocumentLoader(request, substituteData);
japhet@chromium.orgac5cd4b2012-04-12 19:27:28 +0000910 documentLoader->setArchive(archive.get());
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000911 load(documentLoader.get());
912}
jcivelli@chromium.orgc2019dd2011-05-24 19:32:03 +0000913#endif // ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
beidson@apple.comf36a4a12008-03-25 17:11:16 +0000914
darinc370e7e2006-11-08 05:52:27 +0000915String FrameLoader::outgoingReferrer() const
916{
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +0000917 // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
918 // for why we walk the parent chain for srcdoc documents.
akling@apple.com7f50aae2013-08-22 16:01:31 +0000919 Frame* frame = &m_frame;
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +0000920 while (frame->document()->isSrcdocDocument()) {
darin@apple.comfed4d162013-08-25 02:28:06 +0000921 frame = frame->tree().parent();
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +0000922 // Srcdoc documents cannot be top-level documents, by definition,
923 // because they need to be contained in iframes with the srcdoc.
924 ASSERT(frame);
925 }
andersca@apple.comdf550b92013-08-15 22:17:17 +0000926 return frame->loader().m_outgoingReferrer;
darinc370e7e2006-11-08 05:52:27 +0000927}
928
abarth@webkit.orgfb074382008-10-05 19:12:30 +0000929String FrameLoader::outgoingOrigin() const
930{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000931 return m_frame.document()->securityOrigin()->toString();
abarth@webkit.orgfb074382008-10-05 19:12:30 +0000932}
933
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000934bool FrameLoader::checkIfFormActionAllowedByCSP(const URL& url) const
commit-queue@webkit.org78e860e2012-08-16 12:42:09 +0000935{
936 if (m_submittedFormURL.isEmpty())
937 return true;
938
akling@apple.com7f50aae2013-08-22 16:01:31 +0000939 return m_frame.document()->contentSecurityPolicy()->allowFormAction(url);
commit-queue@webkit.org78e860e2012-08-16 12:42:09 +0000940}
941
darinc370e7e2006-11-08 05:52:27 +0000942Frame* FrameLoader::opener()
943{
944 return m_opener;
945}
946
947void FrameLoader::setOpener(Frame* opener)
948{
creis@chromium.org16d76c72012-12-04 17:39:26 +0000949 if (m_opener && !opener)
akling@apple.com7f50aae2013-08-22 16:01:31 +0000950 m_client.didDisownOpener();
creis@chromium.org16d76c72012-12-04 17:39:26 +0000951
darinc370e7e2006-11-08 05:52:27 +0000952 if (m_opener)
akling@apple.com7f50aae2013-08-22 16:01:31 +0000953 m_opener->loader().m_openedFrames.remove(&m_frame);
darinc370e7e2006-11-08 05:52:27 +0000954 if (opener)
akling@apple.com7f50aae2013-08-22 16:01:31 +0000955 opener->loader().m_openedFrames.add(&m_frame);
darinc370e7e2006-11-08 05:52:27 +0000956 m_opener = opener;
weinig343b6ff2007-08-07 03:08:53 +0000957
akling@apple.com7f50aae2013-08-22 16:01:31 +0000958 if (m_frame.document())
959 m_frame.document()->initSecurityContext();
darinc370e7e2006-11-08 05:52:27 +0000960}
961
eric@webkit.org4ffb1fe2010-09-03 04:28:12 +0000962// FIXME: This does not belong in FrameLoader!
darinc370e7e2006-11-08 05:52:27 +0000963void FrameLoader::handleFallbackContent()
964{
akling@apple.com7f50aae2013-08-22 16:01:31 +0000965 HTMLFrameOwnerElement* owner = m_frame.ownerElement();
cdumez@apple.coma9c60c92014-10-02 19:39:41 +0000966 if (!is<HTMLObjectElement>(owner))
darinc370e7e2006-11-08 05:52:27 +0000967 return;
cdumez@apple.com72754ba2014-09-23 22:03:15 +0000968 downcast<HTMLObjectElement>(*owner).renderFallbackContent();
darinc370e7e2006-11-08 05:52:27 +0000969}
970
971void FrameLoader::provisionalLoadStarted()
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +0000972{
973 if (m_stateMachine.firstLayoutDone())
974 m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
akling@apple.com7f50aae2013-08-22 16:01:31 +0000975 m_frame.navigationScheduler().cancel(true);
976 m_client.provisionalLoadStarted();
darinc370e7e2006-11-08 05:52:27 +0000977}
978
darinc370e7e2006-11-08 05:52:27 +0000979void FrameLoader::resetMultipleFormSubmissionProtection()
980{
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000981 m_submittedFormURL = URL();
darinc370e7e2006-11-08 05:52:27 +0000982}
983
abarth@webkit.org622d9df2009-05-22 16:44:47 +0000984void FrameLoader::updateFirstPartyForCookies()
darinc370e7e2006-11-08 05:52:27 +0000985{
darin@apple.comfed4d162013-08-25 02:28:06 +0000986 if (m_frame.tree().parent())
987 setFirstPartyForCookies(m_frame.tree().parent()->document()->firstPartyForCookies());
darinc370e7e2006-11-08 05:52:27 +0000988 else
akling@apple.com7f50aae2013-08-22 16:01:31 +0000989 setFirstPartyForCookies(m_frame.document()->url());
darinc370e7e2006-11-08 05:52:27 +0000990}
991
darin@apple.com5ffbb5c2013-09-27 16:39:41 +0000992void FrameLoader::setFirstPartyForCookies(const URL& url)
darinc370e7e2006-11-08 05:52:27 +0000993{
darin@apple.comfed4d162013-08-25 02:28:06 +0000994 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
darin@apple.comaf8b1a92011-06-25 00:09:37 +0000995 frame->document()->setFirstPartyForCookies(url);
darinc370e7e2006-11-08 05:52:27 +0000996}
997
darin@apple.comd69216d2008-03-11 00:45:47 +0000998// This does the same kind of work that didOpenURL does, except it relies on the fact
darinc370e7e2006-11-08 05:52:27 +0000999// that a higher level already checked that the URLs match and the scrolling is the right thing to do.
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001000void FrameLoader::loadInSameDocument(const URL& url, PassRefPtr<SerializedScriptValue> stateObject, bool isNewNavigation)
darinc370e7e2006-11-08 05:52:27 +00001001{
beidson@apple.com08c61752009-12-03 19:04:40 +00001002 // If we have a state object, we cannot also be a new navigation.
1003 ASSERT(!stateObject || (stateObject && !isNewNavigation));
1004
1005 // Update the data source's request with the new URL to fake the URL change
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001006 URL oldURL = m_frame.document()->url();
akling@apple.com7f50aae2013-08-22 16:01:31 +00001007 m_frame.document()->setURL(url);
jochen@chromium.org7495f962012-05-04 16:43:03 +00001008 setOutgoingReferrer(url);
beidson@apple.com08c61752009-12-03 19:04:40 +00001009 documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
1010 if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
1011 // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add
1012 // based on the current request. Must also happen before we openURL and displace the
1013 // scroll position, since adding the BF item will save away scroll state.
1014
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001015 // NB2: If we were loading a long, slow doc, and the user fragment navigated before
beidson@apple.com08c61752009-12-03 19:04:40 +00001016 // it was done, currItem is now set the that slow doc, and prevItem is whatever was
1017 // before it. Adding the b/f item will bump the slow doc down to prevItem, even
1018 // though its load is not yet done. I think this all works out OK, for one because
1019 // we have already saved away the scroll and doc state for the long slow load,
1020 // but it's not an obvious case.
1021
akling@apple.com672cb852013-08-22 20:27:27 +00001022 history().updateBackForwardListForFragmentScroll();
beidson@apple.com8127cdc2009-08-07 15:35:19 +00001023 }
1024
japhet@chromium.orgb254c9b2011-01-26 19:14:26 +00001025 bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier();
beidson@apple.com43a414c2010-03-19 18:25:21 +00001026
akling@apple.com672cb852013-08-22 20:27:27 +00001027 history().updateForSameDocumentNavigation();
britto@apple.com195cc0b2008-07-23 16:48:47 +00001028
1029 // 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 +00001030 if (hashChange)
akling@apple.com7f50aae2013-08-22 16:01:31 +00001031 m_frame.eventHandler().stopAutoscrollTimer();
beidson@apple.com08c61752009-12-03 19:04:40 +00001032
darinc370e7e2006-11-08 05:52:27 +00001033 // It's important to model this as a load that starts and immediately finishes.
1034 // Otherwise, the parent frame may think we never finished loading.
beidson@apple.com08c61752009-12-03 19:04:40 +00001035 started();
japhet@chromium.org48bb2602010-03-04 23:01:45 +00001036
1037 // We need to scroll to the fragment whether or not a hash change occurred, since
1038 // the user might have scrolled since the previous navigation.
tsepez@chromium.org8d3c2c12012-04-17 19:03:42 +00001039 scrollToFragmentWithParentBoundary(url);
beidson@apple.com08c61752009-12-03 19:04:40 +00001040
darinc370e7e2006-11-08 05:52:27 +00001041 m_isComplete = false;
1042 checkCompleted();
beidson@apple.com08c61752009-12-03 19:04:40 +00001043
1044 if (isNewNavigation) {
1045 // This will clear previousItem from the rest of the frame tree that didn't
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001046 // doing any loading. We need to make a pass on this now, since for fragment
1047 // navigation we'll not go through a real load and reach Completed state.
beidson@apple.com08c61752009-12-03 19:04:40 +00001048 checkLoadComplete();
1049 }
1050
akling@apple.com7f50aae2013-08-22 16:01:31 +00001051 m_client.dispatchDidNavigateWithinPage();
darin@chromium.orgfe279962010-03-16 17:26:59 +00001052
akling@apple.com7f50aae2013-08-22 16:01:31 +00001053 m_frame.document()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue());
1054 m_client.dispatchDidPopStateWithinPage();
beidson@apple.com08c61752009-12-03 19:04:40 +00001055
1056 if (hashChange) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00001057 m_frame.document()->enqueueHashchangeEvent(oldURL, url);
1058 m_client.dispatchDidChangeLocationWithinPage();
beidson@apple.com08c61752009-12-03 19:04:40 +00001059 }
1060
1061 // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
akling@apple.com7f50aae2013-08-22 16:01:31 +00001062 m_client.didFinishLoad();
darinc370e7e2006-11-08 05:52:27 +00001063}
1064
1065bool FrameLoader::isComplete() const
1066{
1067 return m_isComplete;
1068}
1069
darinc370e7e2006-11-08 05:52:27 +00001070void FrameLoader::completed()
1071{
akling@apple.comf8515982013-09-02 18:50:01 +00001072 Ref<Frame> protect(m_frame);
beidson@apple.coma5662512009-10-27 00:19:33 +00001073
darin@apple.comfed4d162013-08-25 02:28:06 +00001074 for (Frame* descendant = m_frame.tree().traverseNext(&m_frame); descendant; descendant = descendant->tree().traverseNext(&m_frame))
akling@apple.com9ce995f2013-08-21 20:54:20 +00001075 descendant->navigationScheduler().startTimer();
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001076
darin@apple.comfed4d162013-08-25 02:28:06 +00001077 if (Frame* parent = m_frame.tree().parent())
andersca@apple.comdf550b92013-08-15 22:17:17 +00001078 parent->loader().checkCompleted();
beidson@apple.coma5662512009-10-27 00:19:33 +00001079
akling@apple.com7f50aae2013-08-22 16:01:31 +00001080 if (m_frame.view())
mmaxfield@apple.com6ebeece2014-12-09 21:03:54 +00001081 m_frame.view()->maintainScrollPositionAtAnchor(nullptr);
weinig@apple.comf2ead0f2013-09-30 04:36:35 +00001082 m_activityAssertion = nullptr;
darinc370e7e2006-11-08 05:52:27 +00001083}
1084
1085void FrameLoader::started()
1086{
barraclough@apple.com85709e42014-09-17 18:27:42 +00001087 if (m_frame.page())
1088 m_activityAssertion = m_frame.page()->pageThrottler().pageLoadActivityToken();
darin@apple.comfed4d162013-08-25 02:28:06 +00001089 for (Frame* frame = &m_frame; frame; frame = frame->tree().parent())
andersca@apple.comdf550b92013-08-15 22:17:17 +00001090 frame->loader().m_isComplete = false;
darinc370e7e2006-11-08 05:52:27 +00001091}
1092
darinc370e7e2006-11-08 05:52:27 +00001093void FrameLoader::prepareForLoadStart()
1094{
japhet@chromium.org7879dd72012-08-30 02:58:37 +00001095 m_progressTracker->progressStarted();
akling@apple.com7f50aae2013-08-22 16:01:31 +00001096 m_client.dispatchDidStartProvisionalLoad();
mario@webkit.org685258f2011-12-06 00:10:55 +00001097
ossy@webkit.org451e9b02014-01-27 12:40:18 +00001098 if (AXObjectCache::accessibilityEnabled()) {
1099 if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache()) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001100 AXObjectCache::AXLoadingEvent loadingEvent = loadType() == FrameLoadType::Reload ? AXObjectCache::AXLoadingReloaded : AXObjectCache::AXLoadingStarted;
ossy@webkit.org451e9b02014-01-27 12:40:18 +00001101 cache->frameLoadingEventNotification(&m_frame, loadingEvent);
1102 }
mario@webkit.org685258f2011-12-06 00:10:55 +00001103 }
darinc370e7e2006-11-08 05:52:27 +00001104}
1105
1106void FrameLoader::setupForReplace()
1107{
akling@apple.com7f50aae2013-08-22 16:01:31 +00001108 m_client.revertToProvisionalState(m_documentLoader.get());
darinc370e7e2006-11-08 05:52:27 +00001109 setState(FrameStateProvisional);
1110 m_provisionalDocumentLoader = m_documentLoader;
cdumez@apple.comd839ea12015-07-04 19:42:18 +00001111 m_documentLoader = nullptr;
darinc370e7e2006-11-08 05:52:27 +00001112 detachChildren();
1113}
1114
beidson@apple.comdab05722015-05-31 05:53:06 +00001115void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, Event* event, PassRefPtr<FormState> formState)
darin@apple.com0f88bda2009-04-02 00:30:50 +00001116{
inferno@chromium.org670ab752011-07-13 18:51:44 +00001117 // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader.
akling@apple.comf8515982013-09-02 18:50:01 +00001118 Ref<Frame> protect(m_frame);
inferno@chromium.org670ab752011-07-13 18:51:44 +00001119
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001120 URL url = request.resourceRequest().url();
antti@apple.comc633dca2008-11-14 21:34:55 +00001121
akling@apple.com7f50aae2013-08-22 16:01:31 +00001122 ASSERT(m_frame.document());
commit-queue@webkit.orgd0654822011-10-04 18:00:32 +00001123 if (!request.requester()->canDisplay(url)) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00001124 reportLocalLoadFailed(&m_frame, url.stringCenterEllipsizedToLength());
darin@apple.com1cf3d562010-12-07 16:23:03 +00001125 return;
1126 }
1127
darin5a1e60e2007-04-17 19:58:16 +00001128 String argsReferrer = request.resourceRequest().httpReferrer();
jochen@chromium.org4761ef52011-11-21 10:29:55 +00001129 if (argsReferrer.isEmpty())
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001130 argsReferrer = outgoingReferrer();
antti@apple.comc633dca2008-11-14 21:34:55 +00001131
akling@apple.com7f50aae2013-08-22 16:01:31 +00001132 String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), url, argsReferrer);
beidson@apple.comee119d42015-04-28 19:38:13 +00001133 if (request.shouldSendReferrer() == NeverSendReferrer)
anderscade5715d2007-01-06 00:55:49 +00001134 referrer = String();
beidson@apple.comee119d42015-04-28 19:38:13 +00001135
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001136 FrameLoadType loadType;
1137 if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001138 loadType = FrameLoadType::Reload;
beidson@apple.comee119d42015-04-28 19:38:13 +00001139 else if (request.lockBackForwardList() == LockBackForwardList::Yes)
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001140 loadType = FrameLoadType::RedirectWithLockedBackForwardList;
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001141 else
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001142 loadType = FrameLoadType::Standard;
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001143
1144 if (request.resourceRequest().httpMethod() == "POST")
beidson@apple.combd66a782015-05-29 16:31:49 +00001145 loadPostRequest(request, referrer, loadType, event, formState.get());
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001146 else
beidson@apple.combd66a782015-05-29 16:31:49 +00001147 loadURL(request, referrer, loadType, event, formState.get());
ggaren@apple.com78b4dc62009-01-30 23:09:43 +00001148
darin@apple.com0f88bda2009-04-02 00:30:50 +00001149 // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
1150 // load if frame names have changed.
akling@apple.com7f50aae2013-08-22 16:01:31 +00001151 Frame* sourceFrame = formState ? formState->sourceDocument()->frame() : &m_frame;
abarth@webkit.orga9da3b02012-03-27 01:09:43 +00001152 if (!sourceFrame)
akling@apple.com7f50aae2013-08-22 16:01:31 +00001153 sourceFrame = &m_frame;
andersca@apple.comdf550b92013-08-15 22:17:17 +00001154 Frame* targetFrame = sourceFrame->loader().findFrameForNavigation(request.frameName());
darin@apple.com0f88bda2009-04-02 00:30:50 +00001155 if (targetFrame && targetFrame != sourceFrame) {
darine0cef432007-07-10 19:21:23 +00001156 if (Page* page = targetFrame->page())
akling@apple.combd774812013-05-17 00:03:01 +00001157 page->chrome().focus();
darin@apple.com0f88bda2009-04-02 00:30:50 +00001158 }
anderscade5715d2007-01-06 00:55:49 +00001159}
ddkilzer@apple.come6e7d422008-08-06 21:15:39 +00001160
mitz@apple.comc99c7152015-07-17 21:16:09 +00001161static ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToApply(Frame& sourceFrame, ShouldOpenExternalURLsPolicy propagatedPolicy)
1162{
1163 if (!sourceFrame.isMainFrame())
1164 return ShouldOpenExternalURLsPolicy::ShouldNotAllow;
1165 if (ScriptController::processingUserGesture())
1166 return ShouldOpenExternalURLsPolicy::ShouldAllow;
1167 return propagatedPolicy;
1168}
1169
beidson@apple.comdab05722015-05-31 05:53:06 +00001170void FrameLoader::loadURL(const FrameLoadRequest& frameLoadRequest, const String& referrer, FrameLoadType newLoadType, Event* event, PassRefPtr<FormState> prpFormState)
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001171{
commit-queue@webkit.orgcd5cda22011-02-15 15:55:21 +00001172 if (m_inStopAllLoaders)
1173 return;
1174
jpfau@apple.com18da22e2014-06-19 00:20:25 +00001175 Ref<Frame> protect(m_frame);
1176
beidson@apple.combd66a782015-05-29 16:31:49 +00001177 String frameName = frameLoadRequest.frameName();
1178 AllowNavigationToInvalidURL allowNavigationToInvalidURL = frameLoadRequest.allowNavigationToInvalidURL();
1179 NewFrameOpenerPolicy openerPolicy = frameLoadRequest.newFrameOpenerPolicy();
1180 LockHistory lockHistory = frameLoadRequest.lockHistory();
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001181 RefPtr<FormState> formState = prpFormState;
andersca3513ce02007-05-17 08:38:44 +00001182 bool isFormSubmission = formState;
beidson@apple.combd66a782015-05-29 16:31:49 +00001183
1184 const URL& newURL = frameLoadRequest.resourceRequest().url();
weinig@apple.comc5002662007-12-12 07:26:19 +00001185 ResourceRequest request(newURL);
abarth@webkit.orgfb074382008-10-05 19:12:30 +00001186 if (!referrer.isEmpty()) {
anderscade5715d2007-01-06 00:55:49 +00001187 request.setHTTPReferrer(referrer);
abarth@webkit.orgfb074382008-10-05 19:12:30 +00001188 RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
abarth@webkit.org48cade32008-10-23 09:43:34 +00001189 addHTTPOriginIfNeeded(request, referrerOrigin->toString());
abarth@webkit.orgfb074382008-10-05 19:12:30 +00001190 }
jpfau@apple.com46b3c4e02013-03-05 00:22:27 +00001191#if ENABLE(CACHE_PARTITIONING)
akling@apple.com52989472013-09-16 20:09:25 +00001192 if (&m_frame.tree().top() != &m_frame)
cdumez@apple.com8730b6e2014-10-21 02:10:47 +00001193 request.setDomainForCachePartition(m_frame.tree().top().document()->securityOrigin()->domainForCachePartition());
jpfau@apple.com46b3c4e02013-03-05 00:22:27 +00001194#endif
jochen@chromium.orgdac140c2011-08-01 21:18:49 +00001195 addExtraFieldsToRequest(request, newLoadType, true);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001196 if (newLoadType == FrameLoadType::Reload || newLoadType == FrameLoadType::ReloadFromOrigin)
anderscade5715d2007-01-06 00:55:49 +00001197 request.setCachePolicy(ReloadIgnoringCacheData);
1198
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001199 ASSERT(newLoadType != FrameLoadType::Same);
anderscade5715d2007-01-06 00:55:49 +00001200
darin@apple.com0f88bda2009-04-02 00:30:50 +00001201 // The search for a target frame is done earlier in the case of form submission.
1202 Frame* targetFrame = isFormSubmission ? 0 : findFrameForNavigation(frameName);
akling@apple.com7f50aae2013-08-22 16:01:31 +00001203 if (targetFrame && targetFrame != &m_frame) {
beidson@apple.combd66a782015-05-29 16:31:49 +00001204 FrameLoadRequest newFrameLoadRequest(frameLoadRequest);
1205 newFrameLoadRequest.setFrameName("_self");
1206 targetFrame->loader().loadURL(newFrameLoadRequest, referrer, newLoadType, event, formState.release());
darin@apple.com19c05e92009-03-30 17:26:16 +00001207 return;
1208 }
1209
cdumez@apple.com83847a92015-06-26 18:26:19 +00001210 if (m_pageDismissalEventBeingDispatched != PageDismissalType::None)
eric@webkit.org6cae31a2009-09-26 02:35:15 +00001211 return;
1212
beidson@apple.com87dc6312015-06-02 18:43:13 +00001213 NavigationAction action(request, newLoadType, isFormSubmission, event, frameLoadRequest.shouldOpenExternalURLsPolicy());
anderscade5715d2007-01-06 00:55:49 +00001214
darin@apple.com19c05e92009-03-30 17:26:16 +00001215 if (!targetFrame && !frameName.isEmpty()) {
mitz@apple.comc99c7152015-07-17 21:16:09 +00001216 action = action.copyWithShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, frameLoadRequest.shouldOpenExternalURLsPolicy()));
ap@apple.coma383f252015-02-14 18:16:00 +00001217 policyChecker().checkNewWindowPolicy(action, request, formState.release(), frameName, [this, allowNavigationToInvalidURL, openerPolicy](const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue) {
1218 continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
andersca@apple.com096333f2013-11-07 21:37:36 +00001219 });
anderscade5715d2007-01-06 00:55:49 +00001220 return;
1221 }
1222
1223 RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
1224
weinig@apple.comc5002662007-12-12 07:26:19 +00001225 bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
yael.aharon@nokia.com79f69052010-12-30 19:31:00 +00001226 const String& httpMethod = request.httpMethod();
anderscade5715d2007-01-06 00:55:49 +00001227
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001228 // Make sure to do scroll to fragment processing even if the URL is
anderscade5715d2007-01-06 00:55:49 +00001229 // exactly the same so pages with '#' links and DHTML side effects
1230 // work properly.
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00001231 if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, newLoadType, newURL)) {
anderscade5715d2007-01-06 00:55:49 +00001232 oldDocumentLoader->setTriggeringAction(action);
andersca@apple.com97ab6d92013-10-21 22:55:14 +00001233 oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001234 policyChecker().stopCheck();
1235 policyChecker().setLoadType(newLoadType);
andersca@apple.com096333f2013-11-07 21:37:36 +00001236 policyChecker().checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(), [this](const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue) {
1237 continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
1238 });
1239 return;
1240 }
1241
1242 // must grab this now, since this load may stop the previous load and clear this flag
1243 bool isRedirect = m_quickRedirectComing;
aestes@apple.com47ac5e12014-08-18 17:48:48 +00001244 loadWithNavigationAction(request, action, lockHistory, newLoadType, formState.release(), allowNavigationToInvalidURL);
andersca@apple.com096333f2013-11-07 21:37:36 +00001245 if (isRedirect) {
1246 m_quickRedirectComing = false;
1247 if (m_provisionalDocumentLoader)
1248 m_provisionalDocumentLoader->setIsClientRedirect(true);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001249 } else if (sameURL && newLoadType != FrameLoadType::Reload && newLoadType != FrameLoadType::ReloadFromOrigin) {
andersca@apple.com096333f2013-11-07 21:37:36 +00001250 // Example of this case are sites that reload the same URL with a different cookie
1251 // driving the generated content, or a master frame with links that drive a target
1252 // frame, where the user has clicked on the same link repeatedly.
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001253 m_loadType = FrameLoadType::Same;
anderscade5715d2007-01-06 00:55:49 +00001254 }
1255}
1256
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001257SubstituteData FrameLoader::defaultSubstituteDataForURL(const URL& url)
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001258{
1259 if (!shouldTreatURLAsSrcdocDocument(url))
1260 return SubstituteData();
akling@apple.com7f50aae2013-08-22 16:01:31 +00001261 String srcdoc = m_frame.ownerElement()->fastGetAttribute(srcdocAttr);
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001262 ASSERT(!srcdoc.isNull());
1263 CString encodedSrcdoc = srcdoc.utf8();
beidson@apple.comceb7cba2015-05-19 22:22:51 +00001264
1265 ResourceResponse response(URL(), ASCIILiteral("text/html"), encodedSrcdoc.length(), ASCIILiteral("UTF-8"));
1266 return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), URL(), response, SubstituteData::SessionHistoryVisibility::Hidden);
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00001267}
1268
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001269void FrameLoader::load(const FrameLoadRequest& passedRequest)
anderscade5715d2007-01-06 00:55:49 +00001270{
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001271 FrameLoadRequest request(passedRequest);
mjs2d326f52007-01-29 12:50:49 +00001272
andersca8567b3d2007-03-21 05:46:49 +00001273 if (m_inStopAllLoaders)
1274 return;
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001275
1276 if (!request.frameName().isEmpty()) {
1277 Frame* frame = findFrameForNavigation(request.frameName());
1278 if (frame) {
1279 request.setShouldCheckNewWindowPolicy(false);
andersca@apple.comdf550b92013-08-15 22:17:17 +00001280 if (&frame->loader() != this) {
1281 frame->loader().load(request);
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001282 return;
1283 }
1284 }
1285 }
1286
1287 if (request.shouldCheckNewWindowPolicy()) {
beidson@apple.com87dc6312015-06-02 18:43:13 +00001288 NavigationAction action(request.resourceRequest(), NavigationType::Other, passedRequest.shouldOpenExternalURLsPolicy());
1289 policyChecker().checkNewWindowPolicy(action, request.resourceRequest(), nullptr, request.frameName(), [this](const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue) {
ap@apple.coma383f252015-02-14 18:16:00 +00001290 continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue, AllowNavigationToInvalidURL::Yes, NewFrameOpenerPolicy::Suppress);
andersca@apple.com096333f2013-11-07 21:37:36 +00001291 });
1292
simonjam@chromium.orgc98850b2012-11-28 01:07:36 +00001293 return;
1294 }
1295
1296 if (!request.hasSubstituteData())
1297 request.setSubstituteData(defaultSubstituteDataForURL(request.resourceRequest().url()));
1298
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001299 Ref<DocumentLoader> loader = m_client.createDocumentLoader(request.resourceRequest(), request.substituteData());
1300 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(loader, request.shouldOpenExternalURLsPolicy());
beidson@apple.comd0558532015-05-28 04:52:25 +00001301
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001302 load(loader.ptr());
anderscade5715d2007-01-06 00:55:49 +00001303}
1304
aestes@apple.com47ac5e12014-08-18 17:48:48 +00001305void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, LockHistory lockHistory, FrameLoadType type, PassRefPtr<FormState> formState, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
anderscade5715d2007-01-06 00:55:49 +00001306{
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001307 Ref<DocumentLoader> loader = m_client.createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1308 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(loader, action.shouldOpenExternalURLsPolicy());
beidson@apple.com87dc6312015-06-02 18:43:13 +00001309
mrowe@apple.combf5eaa62014-04-03 00:51:04 +00001310 if (lockHistory == LockHistory::Yes && m_documentLoader)
commit-queue@webkit.org63040d02011-03-26 00:30:40 +00001311 loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
anderscade5715d2007-01-06 00:55:49 +00001312
1313 loader->setTriggeringAction(action);
1314 if (m_documentLoader)
1315 loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1316
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001317 loadWithDocumentLoader(loader.ptr(), type, formState, allowNavigationToInvalidURL);
anderscade5715d2007-01-06 00:55:49 +00001318}
1319
1320void FrameLoader::load(DocumentLoader* newDocumentLoader)
1321{
anderscade5715d2007-01-06 00:55:49 +00001322 ResourceRequest& r = newDocumentLoader->request();
antti@apple.com4da613e2008-12-15 15:28:41 +00001323 addExtraFieldsToMainResourceRequest(r);
anderscade5715d2007-01-06 00:55:49 +00001324 FrameLoadType type;
1325
1326 if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
1327 r.setCachePolicy(ReloadIgnoringCacheData);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001328 type = FrameLoadType::Same;
1329 } else if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->unreachableURL()) && m_loadType == FrameLoadType::Reload)
1330 type = FrameLoadType::Reload;
jpfau@apple.com6e5a6052012-07-27 00:52:32 +00001331 else
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001332 type = FrameLoadType::Standard;
anderscade5715d2007-01-06 00:55:49 +00001333
1334 if (m_documentLoader)
1335 newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1336
1337 // When we loading alternate content for an unreachable URL that we're
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001338 // visiting in the history list, we treat it as a reload so the history list
anderscade5715d2007-01-06 00:55:49 +00001339 // is appropriately maintained.
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001340 //
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001341 // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadType::Reload" ...
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001342 // shouldn't a more explicit type of reload be defined, that means roughly
1343 // "load without affecting history" ?
mjs2d326f52007-01-29 12:50:49 +00001344 if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
commit-queue@webkit.org072ac242011-04-04 17:05:55 +00001345 // shouldReloadToHandleUnreachableURL() returns true only when the original load type is back-forward.
1346 // In this case we should save the document state now. Otherwise the state can be lost because load type is
1347 // changed and updateForBackForwardNavigation() will not be called when loading is committed.
akling@apple.com672cb852013-08-22 20:27:27 +00001348 history().saveDocumentAndScrollState();
commit-queue@webkit.org072ac242011-04-04 17:05:55 +00001349
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001350 ASSERT(type == FrameLoadType::Standard);
1351 type = FrameLoadType::Reload;
anderscade5715d2007-01-06 00:55:49 +00001352 }
1353
aestes@apple.com47ac5e12014-08-18 17:48:48 +00001354 loadWithDocumentLoader(newDocumentLoader, type, 0, AllowNavigationToInvalidURL::Yes);
anderscade5715d2007-01-06 00:55:49 +00001355}
1356
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001357static void logNavigation(MainFrame& frame, FrameLoadType type)
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001358{
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001359 String navigationDescription;
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001360 switch (type) {
1361 case FrameLoadType::Standard:
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001362 navigationDescription = ASCIILiteral("standard");
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001363 break;
1364 case FrameLoadType::Back:
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001365 navigationDescription = ASCIILiteral("back");
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001366 break;
1367 case FrameLoadType::Forward:
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001368 navigationDescription = ASCIILiteral("forward");
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001369 break;
1370 case FrameLoadType::IndexedBackForward:
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001371 navigationDescription = ASCIILiteral("indexedBackForward");
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001372 break;
1373 case FrameLoadType::Reload:
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001374 navigationDescription = ASCIILiteral("reload");
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001375 break;
1376 case FrameLoadType::Same:
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001377 navigationDescription = ASCIILiteral("same");
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001378 break;
1379 case FrameLoadType::ReloadFromOrigin:
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001380 navigationDescription = ASCIILiteral("reloadFromOrigin");
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001381 break;
1382 case FrameLoadType::Replace:
1383 case FrameLoadType::RedirectWithLockedBackForwardList:
1384 // Not logging those for now.
1385 return;
1386 }
cdumez@apple.com216d2572015-02-23 22:08:45 +00001387 frame.diagnosticLoggingClient().logDiagnosticMessage(DiagnosticLoggingKeys::navigationKey(), navigationDescription, ShouldSample::No);
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001388}
1389
aestes@apple.com47ac5e12014-08-18 17:48:48 +00001390void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
anderscade5715d2007-01-06 00:55:49 +00001391{
inferno@chromium.org6e8e3472010-10-26 13:29:04 +00001392 // Retain because dispatchBeforeLoadEvent may release the last reference to it.
akling@apple.comf8515982013-09-02 18:50:01 +00001393 Ref<Frame> protect(m_frame);
inferno@chromium.org6e8e3472010-10-26 13:29:04 +00001394
akling@apple.com7f50aae2013-08-22 16:01:31 +00001395 ASSERT(m_client.hasWebView());
anderscade5715d2007-01-06 00:55:49 +00001396
1397 // Unfortunately the view must be non-nil, this is ultimately due
1398 // to parser requiring a FrameView. We should fix this dependency.
1399
akling@apple.com7f50aae2013-08-22 16:01:31 +00001400 ASSERT(m_frame.view());
anderscade5715d2007-01-06 00:55:49 +00001401
cdumez@apple.com83847a92015-06-26 18:26:19 +00001402 if (m_pageDismissalEventBeingDispatched != PageDismissalType::None)
abarth@webkit.org89fa3502009-09-21 02:30:12 +00001403 return;
1404
akling@apple.com7f50aae2013-08-22 16:01:31 +00001405 if (m_frame.document())
1406 m_previousURL = m_frame.document()->url();
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001407
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001408 // Log main frame navigation types.
1409 if (m_frame.isMainFrame())
cdumez@apple.com841ecde2015-01-12 22:30:59 +00001410 logNavigation(static_cast<MainFrame&>(m_frame), type);
cdumez@apple.com4c54fa72014-12-18 18:42:27 +00001411
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001412 policyChecker().setLoadType(type);
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001413 RefPtr<FormState> formState = prpFormState;
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00001414 bool isFormSubmission = formState;
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001415
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001416 const URL& newURL = loader->request().url();
yael.aharon@nokia.com79f69052010-12-30 19:31:00 +00001417 const String& httpMethod = loader->request().httpMethod();
anderscade5715d2007-01-06 00:55:49 +00001418
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001419 if (shouldPerformFragmentNavigation(isFormSubmission, httpMethod, policyChecker().loadType(), newURL)) {
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00001420 RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001421 NavigationAction action(loader->request(), policyChecker().loadType(), isFormSubmission);
anderscade5715d2007-01-06 00:55:49 +00001422
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00001423 oldDocumentLoader->setTriggeringAction(action);
andersca@apple.com97ab6d92013-10-21 22:55:14 +00001424 oldDocumentLoader->setLastCheckedRequest(ResourceRequest());
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001425 policyChecker().stopCheck();
andersca@apple.com096333f2013-11-07 21:37:36 +00001426 policyChecker().checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState, [this](const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue) {
1427 continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
1428 });
1429 return;
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00001430 }
andersca@apple.com096333f2013-11-07 21:37:36 +00001431
1432 if (Frame* parent = m_frame.tree().parent())
1433 loader->setOverrideEncoding(parent->loader().documentLoader()->overrideEncoding());
1434
1435 policyChecker().stopCheck();
1436 setPolicyDocumentLoader(loader);
1437 if (loader->triggeringAction().isEmpty())
1438 loader->setTriggeringAction(NavigationAction(loader->request(), policyChecker().loadType(), isFormSubmission));
1439
1440 if (Element* ownerElement = m_frame.ownerElement()) {
1441 // We skip dispatching the beforeload event if we've already
1442 // committed a real document load because the event would leak
1443 // subsequent activity by the frame which the parent frame isn't
1444 // supposed to learn. For example, if the child frame navigated to
1445 // a new URL, the parent frame shouldn't learn the URL.
1446 if (!m_stateMachine.committedFirstRealDocumentLoad()
1447 && !ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) {
aestes@apple.com47ac5e12014-08-18 17:48:48 +00001448 continueLoadAfterNavigationPolicy(loader->request(), formState, false, allowNavigationToInvalidURL);
andersca@apple.com096333f2013-11-07 21:37:36 +00001449 return;
1450 }
1451 }
1452
aestes@apple.com47ac5e12014-08-18 17:48:48 +00001453 policyChecker().checkNavigationPolicy(loader->request(), loader, formState, [this, allowNavigationToInvalidURL](const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue) {
1454 continueLoadAfterNavigationPolicy(request, formState, shouldContinue, allowNavigationToInvalidURL);
andersca@apple.com096333f2013-11-07 21:37:36 +00001455 });
anderscade5715d2007-01-06 00:55:49 +00001456}
1457
aroben@apple.com92cfa902008-04-16 19:19:00 +00001458void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
kmccullo23d362f2007-04-06 01:05:58 +00001459{
1460 ASSERT(!url.isEmpty());
aroben@apple.com92cfa902008-04-16 19:19:00 +00001461 if (!frame)
1462 return;
1463
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00001464 frame->document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Not allowed to load local resource: " + url);
kmccullo23d362f2007-04-06 01:05:58 +00001465}
1466
anderscade5715d2007-01-06 00:55:49 +00001467const ResourceRequest& FrameLoader::initialRequest() const
1468{
andersca@apple.com48ffa332008-03-13 19:08:06 +00001469 return activeDocumentLoader()->originalRequest();
anderscade5715d2007-01-06 00:55:49 +00001470}
1471
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001472bool FrameLoader::willLoadMediaElementURL(URL& url)
weinig@apple.com68935252009-10-07 02:48:12 +00001473{
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001474#if PLATFORM(IOS)
1475 // MobileStore depends on the iOS 4.0 era client delegate method because webView:resource:willSendRequest:redirectResponse:fromDataSource
1476 // doesn't let them tell when a load request is coming from a media element. See <rdar://problem/8266916> for more details.
1477 if (applicationIsMobileStore())
1478 return m_client.shouldLoadMediaElementURL(url);
1479#endif
1480
weinig@apple.com68935252009-10-07 02:48:12 +00001481 ResourceRequest request(url);
1482
1483 unsigned long identifier;
1484 ResourceError error;
1485 requestFromDelegate(request, identifier, error);
antti@apple.com021dc012014-09-04 20:00:11 +00001486 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, ResourceResponse(url, String(), -1, String()), 0, -1, -1, error);
weinig@apple.com68935252009-10-07 02:48:12 +00001487
1488 url = request.url();
1489
1490 return error.isNull();
1491}
1492
mjs2d326f52007-01-29 12:50:49 +00001493bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
anderscade5715d2007-01-06 00:55:49 +00001494{
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001495 URL unreachableURL = docLoader->unreachableURL();
anderscade5715d2007-01-06 00:55:49 +00001496
1497 if (unreachableURL.isEmpty())
1498 return false;
1499
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001500 if (!isBackForwardLoadType(policyChecker().loadType()))
anderscade5715d2007-01-06 00:55:49 +00001501 return false;
1502
1503 // We only treat unreachableURLs specially during the delegate callbacks
1504 // for provisional load errors and navigation policy decisions. The former
1505 // case handles well-formed URLs that can't be loaded, and the latter
1506 // case handles malformed URLs and unknown schemes. Loading alternate content
1507 // at other times behaves like a standard load.
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001508 if (policyChecker().delegateIsDecidingNavigationPolicy() || policyChecker().delegateIsHandlingUnimplementablePolicy())
mitz@apple.com6699e272015-05-01 23:47:03 +00001509 return m_policyDocumentLoader && unreachableURL == m_policyDocumentLoader->request().url();
anderscade5715d2007-01-06 00:55:49 +00001510
mitz@apple.com6699e272015-05-01 23:47:03 +00001511 return unreachableURL == m_provisionalLoadErrorBeingHandledURL;
anderscade5715d2007-01-06 00:55:49 +00001512}
1513
ggaren@apple.com3eaa7c02009-01-29 07:38:54 +00001514void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
anderscade5715d2007-01-06 00:55:49 +00001515{
1516 if (!m_documentLoader)
1517 return;
1518
1519 ResourceRequest request = m_documentLoader->request();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001520 URL unreachableURL = m_documentLoader->unreachableURL();
anderscade5715d2007-01-06 00:55:49 +00001521 if (!unreachableURL.isEmpty())
1522 request.setURL(unreachableURL);
1523
ap@apple.com8d5f01b2013-01-07 18:40:55 +00001524 // FIXME: If the resource is a result of form submission and is not cached, the form will be silently resubmitted.
1525 // We should ask the user for confirmation in this case.
anderscade5715d2007-01-06 00:55:49 +00001526 request.setCachePolicy(ReturnCacheDataElseLoad);
1527
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001528 Ref<DocumentLoader> loader = m_client.createDocumentLoader(request, defaultSubstituteDataForURL(request.url()));
1529 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(loader, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
beidson@apple.com87dc6312015-06-02 18:43:13 +00001530
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001531 setPolicyDocumentLoader(loader.ptr());
anderscade5715d2007-01-06 00:55:49 +00001532
1533 loader->setOverrideEncoding(encoding);
1534
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001535 loadWithDocumentLoader(loader.ptr(), FrameLoadType::Reload, 0, AllowNavigationToInvalidURL::Yes);
anderscade5715d2007-01-06 00:55:49 +00001536}
1537
achristensen@apple.comd40e0ba2015-10-14 20:03:14 +00001538void FrameLoader::reload(bool endToEndReload, bool contentBlockersEnabled)
anderscade5715d2007-01-06 00:55:49 +00001539{
1540 if (!m_documentLoader)
1541 return;
1542
anderscade5715d2007-01-06 00:55:49 +00001543 // If a window is created by javascript, its main frame can have an empty but non-nil URL.
1544 // Reloading in this case will lose the current contents (see 4151001).
darin@chromium.org48246852008-11-04 19:40:56 +00001545 if (m_documentLoader->request().url().isEmpty())
anderscade5715d2007-01-06 00:55:49 +00001546 return;
1547
1548 // Replace error-page URL with the URL we were trying to reach.
commit-queue@webkit.org2090e272012-06-28 16:05:43 +00001549 ResourceRequest initialRequest = m_documentLoader->request();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001550 URL unreachableURL = m_documentLoader->unreachableURL();
anderscade5715d2007-01-06 00:55:49 +00001551 if (!unreachableURL.isEmpty())
darin@chromium.org48246852008-11-04 19:40:56 +00001552 initialRequest.setURL(unreachableURL);
commit-queue@webkit.org2090e272012-06-28 16:05:43 +00001553
mrowe@apple.com713db2e2008-07-27 03:49:29 +00001554 // Create a new document loader for the reload, this will become m_documentLoader eventually,
1555 // but first it has to be the "policy" document loader, and then the "provisional" document loader.
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001556 Ref<DocumentLoader> loader = m_client.createDocumentLoader(initialRequest, defaultSubstituteDataForURL(initialRequest.url()));
1557 applyShouldOpenExternalURLsPolicyToNewDocumentLoader(loader, m_documentLoader->shouldOpenExternalURLsPolicyToPropagate());
anderscade5715d2007-01-06 00:55:49 +00001558
achristensen@apple.comd40e0ba2015-10-14 20:03:14 +00001559 loader->setUserContentExtensionsEnabled(contentBlockersEnabled);
1560
anderscade5715d2007-01-06 00:55:49 +00001561 ResourceRequest& request = loader->request();
1562
antti@apple.com4da613e2008-12-15 15:28:41 +00001563 // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
anderscade5715d2007-01-06 00:55:49 +00001564 request.setCachePolicy(ReloadIgnoringCacheData);
1565
1566 // If we're about to re-post, set up action so the application can warn the user.
1567 if (request.httpMethod() == "POST")
beidson@apple.com32654c42015-04-27 18:46:15 +00001568 loader->setTriggeringAction(NavigationAction(request, NavigationType::FormResubmitted));
anderscade5715d2007-01-06 00:55:49 +00001569
1570 loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1571
gyuyoung.kim@webkit.orgc39073e2015-07-19 00:16:50 +00001572 loadWithDocumentLoader(loader.ptr(), endToEndReload ? FrameLoadType::ReloadFromOrigin : FrameLoadType::Reload, 0, AllowNavigationToInvalidURL::Yes);
anderscade5715d2007-01-06 00:55:49 +00001573}
1574
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +00001575void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
darinc370e7e2006-11-08 05:52:27 +00001576{
akling@apple.com7f50aae2013-08-22 16:01:31 +00001577 ASSERT(!m_frame.document() || !m_frame.document()->inPageCache());
cdumez@apple.com83847a92015-06-26 18:26:19 +00001578 if (m_pageDismissalEventBeingDispatched != PageDismissalType::None)
weinig@apple.comf239bbf2009-04-09 18:30:32 +00001579 return;
1580
darinc370e7e2006-11-08 05:52:27 +00001581 // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
1582 if (m_inStopAllLoaders)
1583 return;
inferno@chromium.orgbc05aa52012-08-06 16:30:40 +00001584
1585 // Calling stopLoading() on the provisional document loader can blow away
1586 // the frame from underneath.
akling@apple.comf8515982013-09-02 18:50:01 +00001587 Ref<Frame> protect(m_frame);
darinc370e7e2006-11-08 05:52:27 +00001588
1589 m_inStopAllLoaders = true;
1590
akling@apple.com24f4d6c2013-09-08 08:17:10 +00001591 policyChecker().stopCheck();
darinc370e7e2006-11-08 05:52:27 +00001592
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00001593 // If no new load is in progress, we should clear the provisional item from history
1594 // before we call stopLoading.
1595 if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00001596 history().setProvisionalItem(nullptr);
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00001597
darin@apple.comfed4d162013-08-25 02:28:06 +00001598 for (RefPtr<Frame> child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
andersca@apple.comdf550b92013-08-15 22:17:17 +00001599 child->loader().stopAllLoaders(clearProvisionalItemPolicy);
darin7208e932007-02-13 17:52:53 +00001600 if (m_provisionalDocumentLoader)
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +00001601 m_provisionalDocumentLoader->stopLoading();
beidson@apple.com46421212008-08-25 21:48:56 +00001602 if (m_documentLoader)
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +00001603 m_documentLoader->stopLoading();
beidson@apple.com46421212008-08-25 21:48:56 +00001604
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00001605 setProvisionalDocumentLoader(nullptr);
darin7208e932007-02-13 17:52:53 +00001606
ap@apple.com376647e2010-01-21 23:19:57 +00001607 m_checkTimer.stop();
1608
darinc370e7e2006-11-08 05:52:27 +00001609 m_inStopAllLoaders = false;
1610}
1611
beidson398923b2007-07-31 20:29:02 +00001612void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
mjs8d620d52007-05-10 12:31:42 +00001613{
1614 stopAllLoaders();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001615
1616#if PLATFORM(IOS)
1617 // Lay out immediately when stopping to immediately clear the old page if we just committed this one
1618 // but haven't laid out/painted yet.
1619 // FIXME: Is this behavior specific to iOS? Or should we expose a setting to toggle this behavior?
1620 if (m_frame.view() && !m_frame.view()->didFirstLayout())
1621 m_frame.view()->layout();
1622#endif
1623
beidson398923b2007-07-31 20:29:02 +00001624 if (deferCheckLoadComplete)
1625 scheduleCheckLoadComplete();
akling@apple.com7f50aae2013-08-22 16:01:31 +00001626 else if (m_frame.page())
mjs8d620d52007-05-10 12:31:42 +00001627 checkLoadComplete();
1628}
1629
darinc370e7e2006-11-08 05:52:27 +00001630DocumentLoader* FrameLoader::activeDocumentLoader() const
1631{
1632 if (m_state == FrameStateProvisional)
1633 return m_provisionalDocumentLoader.get();
1634 return m_documentLoader.get();
1635}
1636
darinc370e7e2006-11-08 05:52:27 +00001637bool FrameLoader::isLoading() const
1638{
darin8207db42007-02-20 18:18:39 +00001639 DocumentLoader* docLoader = activeDocumentLoader();
1640 if (!docLoader)
1641 return false;
japhet@chromium.org4bcb80b2012-03-26 20:34:00 +00001642 return docLoader->isLoading();
darinc370e7e2006-11-08 05:52:27 +00001643}
1644
mjs7545bb52007-05-15 08:24:53 +00001645bool FrameLoader::frameHasLoaded() const
1646{
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00001647 return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument());
mjs7545bb52007-05-15 08:24:53 +00001648}
1649
darinc370e7e2006-11-08 05:52:27 +00001650void FrameLoader::setDocumentLoader(DocumentLoader* loader)
1651{
1652 if (!loader && !m_documentLoader)
1653 return;
1654
1655 ASSERT(loader != m_documentLoader);
1656 ASSERT(!loader || loader->frameLoader() == this);
1657
akling@apple.com7f50aae2013-08-22 16:01:31 +00001658 m_client.prepareForDataSourceReplacement();
darinc3d26052007-03-22 18:17:12 +00001659 detachChildren();
japhet@chromium.orga9a58bb2012-09-01 01:09:02 +00001660
1661 // detachChildren() can trigger this frame's unload event, and therefore
1662 // script can run and do just about anything. For example, an unload event that calls
1663 // document.write("") on its parent frame can lead to a recursive detachChildren()
1664 // invocation for this frame. In that case, we can end up at this point with a
1665 // loader that hasn't been deleted but has been detached from its frame. Such a
1666 // DocumentLoader has been sufficiently detached that we'll end up in an inconsistent
1667 // state if we try to use it.
1668 if (loader && !loader->frame())
1669 return;
1670
darinc370e7e2006-11-08 05:52:27 +00001671 if (m_documentLoader)
1672 m_documentLoader->detachFromFrame();
1673
1674 m_documentLoader = loader;
1675}
1676
darinc370e7e2006-11-08 05:52:27 +00001677void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
1678{
1679 if (m_policyDocumentLoader == loader)
1680 return;
1681
darinc370e7e2006-11-08 05:52:27 +00001682 if (loader)
beidson@apple.com10a537f2015-07-09 22:30:42 +00001683 loader->attachToFrame(m_frame);
darinc370e7e2006-11-08 05:52:27 +00001684 if (m_policyDocumentLoader
1685 && m_policyDocumentLoader != m_provisionalDocumentLoader
1686 && m_policyDocumentLoader != m_documentLoader)
1687 m_policyDocumentLoader->detachFromFrame();
1688
1689 m_policyDocumentLoader = loader;
1690}
eric@webkit.org14774f42008-04-21 17:50:37 +00001691
darinc370e7e2006-11-08 05:52:27 +00001692void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
1693{
1694 ASSERT(!loader || !m_provisionalDocumentLoader);
1695 ASSERT(!loader || loader->frameLoader() == this);
1696
1697 if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
1698 m_provisionalDocumentLoader->detachFromFrame();
1699
1700 m_provisionalDocumentLoader = loader;
1701}
1702
darinc370e7e2006-11-08 05:52:27 +00001703void FrameLoader::setState(FrameState newState)
1704{
1705 m_state = newState;
1706
1707 if (newState == FrameStateProvisional)
1708 provisionalLoadStarted();
1709 else if (newState == FrameStateComplete) {
1710 frameLoadCompleted();
darinc370e7e2006-11-08 05:52:27 +00001711 if (m_documentLoader)
1712 m_documentLoader->stopRecordingResponses();
1713 }
1714}
1715
1716void FrameLoader::clearProvisionalLoad()
1717{
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00001718 setProvisionalDocumentLoader(nullptr);
japhet@chromium.org7879dd72012-08-30 02:58:37 +00001719 m_progressTracker->progressCompleted();
darinc370e7e2006-11-08 05:52:27 +00001720 setState(FrameStateComplete);
1721}
1722
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00001723void FrameLoader::commitProvisionalLoad()
beidson50c3bd82007-01-03 03:11:18 +00001724{
beidson50c3bd82007-01-03 03:11:18 +00001725 RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
akling@apple.comf8515982013-09-02 18:50:01 +00001726 Ref<Frame> protect(m_frame);
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00001727
andersca@apple.come776c2f2014-01-18 01:47:19 +00001728 std::unique_ptr<CachedPage> cachedPage;
cdumez@apple.com67e10f72015-01-29 18:38:51 +00001729 if (m_loadingFromCachedPage && history().provisionalItem())
cdumez@apple.com4faf1ef2015-01-30 20:49:33 +00001730 cachedPage = PageCache::singleton().take(*history().provisionalItem(), m_frame.page());
akling@apple.com9663f4b2013-09-05 21:25:32 +00001731
darin@apple.comfed4d162013-08-25 02:28:06 +00001732 LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s'", m_frame.tree().uniqueName().string().utf8().data(),
akling@apple.com7f50aae2013-08-22 16:01:31 +00001733 m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "",
mkwst@chromium.org6f6d9bc2013-05-30 12:08:58 +00001734 pdl ? pdl->url().stringCenterEllipsizedToLength().utf8().data() : "<no provisional DocumentLoader>");
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00001735
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001736#if PLATFORM(IOS)
1737 // In the case where we are not navigating to a cached page, and the system is under (speculative) memory pressure,
1738 // we can try to preemptively release some of the pages in the cache.
1739 // FIXME: Right now the capacity is 1 on iOS devices with 256 MB of RAM, so this will always blow away the whole
1740 // page cache. We could still preemptively prune the page cache while navigating to a cached page if capacity > 1.
1741 // See <rdar://problem/11779846> for more details.
1742 if (!cachedPage) {
cdumez@apple.com681b4aa2015-02-17 17:30:34 +00001743 if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001744 LOG(MemoryPressure, "Pruning page cache because under memory pressure at: %s", __PRETTY_FUNCTION__);
1745 LOG(PageCache, "Pruning page cache to 0 due to memory pressure");
1746 // Don't cache any page if we are under memory pressure.
cdumez@apple.com4faf1ef2015-01-30 20:49:33 +00001747 PageCache::singleton().pruneToSizeNow(0, PruningReason::MemoryPressure);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001748 } else if (systemMemoryLevel() <= memoryLevelThresholdToPrunePageCache) {
1749 LOG(MemoryPressure, "Pruning page cache because system memory level is %d at: %s", systemMemoryLevel(), __PRETTY_FUNCTION__);
cdumez@apple.com4faf1ef2015-01-30 20:49:33 +00001750 auto& pageCache = PageCache::singleton();
1751 LOG(PageCache, "Pruning page cache to %d due to low memory (level %d less or equal to %d threshold)", pageCache.maxSize() / 2, systemMemoryLevel(), memoryLevelThresholdToPrunePageCache);
1752 pageCache.pruneToSizeNow(pageCache.maxSize() / 2, PruningReason::MemoryPressure);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001753 }
1754 }
1755#endif
1756
ap@apple.come042b632013-05-17 20:04:43 +00001757 willTransitionToCommitted();
1758
adachan@apple.com0781d122008-01-11 23:56:40 +00001759 // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
1760 // We are doing this here because we know for sure that a new page is about to be loaded.
cdumez@apple.com67e10f72015-01-29 18:38:51 +00001761 HistoryItem& item = *history().currentItem();
cdumez@apple.com4faf1ef2015-01-30 20:49:33 +00001762 if (!m_frame.tree().parent() && PageCache::singleton().canCache(m_frame.page()) && !item.isInPageCache())
1763 PageCache::singleton().add(item, *m_frame.page());
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001764
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001765 if (m_loadType != FrameLoadType::Replace)
beidson50c3bd82007-01-03 03:11:18 +00001766 closeOldDataSources();
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001767
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00001768 if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
akling@apple.com7f50aae2013-08-22 16:01:31 +00001769 m_client.makeRepresentation(pdl.get());
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001770
akling@apple.com9663f4b2013-09-05 21:25:32 +00001771 transitionToCommitted(cachedPage.get());
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001772
abarth@webkit.orgf12783f2012-10-03 19:34:30 +00001773 if (pdl && m_documentLoader) {
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001774 // Check if the destination page is allowed to access the previous page's timing information.
akling@apple.com6eea45d2014-12-17 01:48:38 +00001775 Ref<SecurityOrigin> securityOrigin(SecurityOrigin::create(pdl->request().url()));
akling@apple.com5a7607f2015-01-21 22:33:49 +00001776 m_documentLoader->timing().setHasSameOriginAsPreviousDocument(securityOrigin.get().canRequest(m_previousURL));
simonjam@chromium.org92bc9b02011-01-06 02:41:13 +00001777 }
1778
beidsonb72fe2e2007-05-03 21:35:24 +00001779 // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
beidson50c3bd82007-01-03 03:11:18 +00001780 // status has changed, if there was a redirect. The frame load delegate may have saved some state about
1781 // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are
1782 // just about to commit a new page, there cannot possibly be a pending redirect at this point.
1783 if (m_sentRedirectNotification)
1784 clientRedirectCancelledOrFinished(false);
1785
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00001786 if (cachedPage && cachedPage->document()) {
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001787#if PLATFORM(IOS)
1788 // FIXME: CachedPage::restore() would dispatch viewport change notification. However UIKit expects load
1789 // commit to happen before any changes to viewport arguments and dealing with this there is difficult.
1790 m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(true);
1791#endif
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00001792 prepareForCachedPageRestore();
commit-queue@webkit.orgcbb6a492010-09-20 20:20:25 +00001793
akling@apple.com9663f4b2013-09-05 21:25:32 +00001794 // FIXME: This API should be turned around so that we ground CachedPage into the Page.
1795 cachedPage->restore(*m_frame.page());
commit-queue@webkit.org1686e5d2012-10-19 23:13:08 +00001796
commit-queue@webkit.orgcbb6a492010-09-20 20:20:25 +00001797 dispatchDidCommitLoad();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001798#if PLATFORM(IOS)
1799 m_frame.page()->chrome().setDispatchViewportDataDidChangeSuppressed(false);
1800 m_frame.page()->chrome().dispatchViewportPropertiesDidChange(m_frame.page()->viewportArguments());
1801#endif
commit-queue@webkit.orgcbb6a492010-09-20 20:20:25 +00001802 // If we have a title let the WebView know about it.
evan@chromium.orgc3532e92011-03-31 15:17:13 +00001803 StringWithDirection title = m_documentLoader->title();
1804 if (!title.isNull())
akling@apple.com7f50aae2013-08-22 16:01:31 +00001805 m_client.dispatchDidReceiveTitle(title);
commit-queue@webkit.orgcbb6a492010-09-20 20:20:25 +00001806
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00001807 checkCompleted();
akling@apple.com9663f4b2013-09-05 21:25:32 +00001808 } else
abarth@webkit.org55d49da2011-06-20 23:32:54 +00001809 didOpenURL();
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00001810
darin@apple.comfed4d162013-08-25 02:28:06 +00001811 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 +00001812 m_frame.document() ? m_frame.document()->url().stringCenterEllipsizedToLength().utf8().data() : "");
beidson@apple.com3a5e3b92009-01-27 08:05:59 +00001813
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001814 if (m_loadType == FrameLoadType::Standard && m_documentLoader->isClientRedirect())
akling@apple.com672cb852013-08-22 20:27:27 +00001815 history().updateForClientRedirect();
beidson@apple.com028c7a72009-02-11 22:01:22 +00001816
beidson@apple.comac095c02009-08-18 01:37:56 +00001817 if (m_loadingFromCachedPage) {
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001818#if PLATFORM(IOS)
1819 // Note, didReceiveDocType is expected to be called for cached pages. See <rdar://problem/5906758> for more details.
1820 if (m_frame.document()->doctype() && m_frame.page())
1821 m_frame.page()->chrome().didReceiveDocType(&m_frame);
1822#endif
akling@apple.com7f50aae2013-08-22 16:01:31 +00001823 m_frame.document()->documentDidResumeFromPageCache();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001824
beidson@apple.com028c7a72009-02-11 22:01:22 +00001825 // Force a layout to update view size and thereby update scrollbars.
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001826#if PLATFORM(IOS)
simon.fraser@apple.com72978b32014-03-09 18:14:07 +00001827 if (!m_client.forceLayoutOnRestoreFromPageCache())
1828 m_frame.view()->forceLayout();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001829#else
akling@apple.com7f50aae2013-08-22 16:01:31 +00001830 m_frame.view()->forceLayout();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001831#endif
beidson@apple.com028c7a72009-02-11 22:01:22 +00001832
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00001833 for (auto& response : m_documentLoader->responses()) {
beidson@apple.com028c7a72009-02-11 22:01:22 +00001834 // FIXME: If the WebKit client changes or cancels the request, this is not respected.
1835 ResourceError error;
1836 unsigned long identifier;
1837 ResourceRequest request(response.url());
1838 requestFromDelegate(request, identifier, error);
1839 // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
1840 // However, with today's computers and networking speeds, this won't happen in practice.
1841 // Could be an issue with a giant local file.
akling@apple.com654fd9a2013-10-06 21:07:29 +00001842 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, request, response, 0, static_cast<int>(response.expectedContentLength()), 0, error);
beidson@apple.com028c7a72009-02-11 22:01:22 +00001843 }
beidson@apple.com028c7a72009-02-11 22:01:22 +00001844
beidson@apple.com028c7a72009-02-11 22:01:22 +00001845 // FIXME: Why only this frame and not parent frames?
1846 checkLoadCompleteForThisFrame();
1847 }
beidson50c3bd82007-01-03 03:11:18 +00001848}
1849
akling@apple.com9663f4b2013-09-05 21:25:32 +00001850void FrameLoader::transitionToCommitted(CachedPage* cachedPage)
beidson50c3bd82007-01-03 03:11:18 +00001851{
akling@apple.com7f50aae2013-08-22 16:01:31 +00001852 ASSERT(m_client.hasWebView());
beidson50c3bd82007-01-03 03:11:18 +00001853 ASSERT(m_state == FrameStateProvisional);
1854
1855 if (m_state != FrameStateProvisional)
1856 return;
1857
akling@apple.com7f50aae2013-08-22 16:01:31 +00001858 if (FrameView* view = m_frame.view()) {
bdakin@apple.com3fec69c2012-03-23 21:02:51 +00001859 if (ScrollAnimator* scrollAnimator = view->existingScrollAnimator())
bdakin@apple.com87235fc2012-03-23 20:36:31 +00001860 scrollAnimator->cancelAnimations();
1861 }
bdakin@apple.come0a38ad2011-03-15 18:30:41 +00001862
akling@apple.com7f50aae2013-08-22 16:01:31 +00001863 m_client.setCopiesOnScroll();
akling@apple.com672cb852013-08-22 20:27:27 +00001864 history().updateForCommit();
beidson50c3bd82007-01-03 03:11:18 +00001865
1866 // The call to closeURL() invokes the unload event handler, which can execute arbitrary
1867 // JavaScript. If the script initiates a new load, we need to abandon the current load,
1868 // or the two will stomp each other.
1869 DocumentLoader* pdl = m_provisionalDocumentLoader.get();
mjs8d620d52007-05-10 12:31:42 +00001870 if (m_documentLoader)
1871 closeURL();
beidson50c3bd82007-01-03 03:11:18 +00001872 if (pdl != m_provisionalDocumentLoader)
1873 return;
1874
beidson4a289132007-05-03 18:50:41 +00001875 // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
1876 if (m_documentLoader)
1877 m_documentLoader->stopLoadingSubresources();
1878 if (m_documentLoader)
1879 m_documentLoader->stopLoadingPlugIns();
1880
1881 setDocumentLoader(m_provisionalDocumentLoader.get());
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00001882 setProvisionalDocumentLoader(nullptr);
japhet@chromium.orga9a58bb2012-09-01 01:09:02 +00001883
1884 if (pdl != m_documentLoader) {
1885 ASSERT(m_state == FrameStateComplete);
1886 return;
1887 }
1888
commit-queue@webkit.org1af3b432011-08-05 07:00:47 +00001889 setState(FrameStateCommittedPage);
beidson50c3bd82007-01-03 03:11:18 +00001890
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00001891#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
darin@apple.com0e83ab12013-09-28 17:19:04 +00001892 if (m_frame.isMainFrame())
akling@apple.com7f50aae2013-08-22 16:01:31 +00001893 m_frame.page()->chrome().client().needTouchEvents(false);
commit-queue@webkit.org52b68332011-06-07 16:20:07 +00001894#endif
1895
beidson50c3bd82007-01-03 03:11:18 +00001896 // Handle adding the URL to the back/forward list.
1897 DocumentLoader* dl = m_documentLoader.get();
beidson50c3bd82007-01-03 03:11:18 +00001898
1899 switch (m_loadType) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001900 case FrameLoadType::Forward:
1901 case FrameLoadType::Back:
1902 case FrameLoadType::IndexedBackForward:
1903 if (m_frame.page()) {
1904 // If the first load within a frame is a navigation within a back/forward list that was attached
1905 // without any of the items being loaded then we need to update the history in a similar manner as
1906 // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
1907 if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame.isMainFrame())
1908 history().updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
mrowe@apple.com04fa4872010-06-16 02:23:45 +00001909
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001910 history().updateForBackForwardNavigation();
beidson50c3bd82007-01-03 03:11:18 +00001911
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001912 // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
1913 if (history().currentItem() && !cachedPage)
1914 m_pendingStateObject = history().currentItem()->stateObject();
mrowe@apple.com04fa4872010-06-16 02:23:45 +00001915
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001916 // Create a document view for this document, or used the cached view.
1917 if (cachedPage) {
1918 DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
1919 ASSERT(cachedDocumentLoader);
beidson@apple.com10a537f2015-07-09 22:30:42 +00001920 cachedDocumentLoader->attachToFrame(m_frame);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001921 m_client.transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
1922 } else
1923 m_client.transitionToCommittedForNewPage();
1924 }
1925 break;
beidson50c3bd82007-01-03 03:11:18 +00001926
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001927 case FrameLoadType::Reload:
1928 case FrameLoadType::ReloadFromOrigin:
1929 case FrameLoadType::Same:
1930 case FrameLoadType::Replace:
1931 history().updateForReload();
1932 m_client.transitionToCommittedForNewPage();
1933 break;
beidson50c3bd82007-01-03 03:11:18 +00001934
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001935 case FrameLoadType::Standard:
1936 history().updateForStandardLoad();
1937 if (m_frame.view())
1938 m_frame.view()->setScrollbarsSuppressed(true);
1939 m_client.transitionToCommittedForNewPage();
1940 break;
beidson50c3bd82007-01-03 03:11:18 +00001941
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001942 case FrameLoadType::RedirectWithLockedBackForwardList:
1943 history().updateForRedirectWithLockedBackForwardList();
1944 m_client.transitionToCommittedForNewPage();
1945 break;
beidson50c3bd82007-01-03 03:11:18 +00001946
andersca@apple.comb50fcc32014-06-19 00:13:20 +00001947 // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
1948 // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
1949 default:
1950 ASSERT_NOT_REACHED();
beidson50c3bd82007-01-03 03:11:18 +00001951 }
1952
weinig@apple.comee87b2f2013-10-05 23:59:58 +00001953 m_documentLoader->writer().setMIMEType(dl->responseMIMEType());
weinig92883332007-02-20 01:05:27 +00001954
beidson50c3bd82007-01-03 03:11:18 +00001955 // Tell the client we've committed this URL.
akling@apple.com7f50aae2013-08-22 16:01:31 +00001956 ASSERT(m_frame.view());
mjs8d620d52007-05-10 12:31:42 +00001957
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00001958 if (m_stateMachine.creatingInitialEmptyDocument())
mjs8d620d52007-05-10 12:31:42 +00001959 return;
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00001960
1961 if (!m_stateMachine.committedFirstRealDocumentLoad())
1962 m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
beidson50c3bd82007-01-03 03:11:18 +00001963}
1964
darinc370e7e2006-11-08 05:52:27 +00001965void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
1966{
1967 // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
1968 // the redirect succeeded. We should either rename this API, or add a new method, like
1969 // -webView:didFinishClientRedirectForFrame:
akling@apple.com7f50aae2013-08-22 16:01:31 +00001970 m_client.dispatchDidCancelClientRedirect();
darinc370e7e2006-11-08 05:52:27 +00001971
1972 if (!cancelWithLoadInProgress)
1973 m_quickRedirectComing = false;
1974
1975 m_sentRedirectNotification = false;
1976}
1977
mrowe@apple.combf5eaa62014-04-03 00:51:04 +00001978void FrameLoader::clientRedirected(const URL& url, double seconds, double fireDate, LockBackForwardList lockBackForwardList)
darinc370e7e2006-11-08 05:52:27 +00001979{
akling@apple.com7f50aae2013-08-22 16:01:31 +00001980 m_client.dispatchWillPerformClientRedirect(url, seconds, fireDate);
darinc370e7e2006-11-08 05:52:27 +00001981
1982 // Remember that we sent a redirect notification to the frame load delegate so that when we commit
1983 // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
1984 m_sentRedirectNotification = true;
1985
darin@apple.com0f88bda2009-04-02 00:30:50 +00001986 // If a "quick" redirect comes in, we set a special mode so we treat the next
1987 // load as part of the original navigation. If we don't have a document loader, we have
darinc370e7e2006-11-08 05:52:27 +00001988 // 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 +00001989 // Loads triggered by JavaScript form submissions never count as quick redirects.
mrowe@apple.combf5eaa62014-04-03 00:51:04 +00001990 m_quickRedirectComing = (lockBackForwardList == LockBackForwardList::Yes || history().currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
darinc370e7e2006-11-08 05:52:27 +00001991}
1992
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00001993bool FrameLoader::shouldReload(const URL& currentURL, const URL& destinationURL)
darinc370e7e2006-11-08 05:52:27 +00001994{
1995 // This function implements the rule: "Don't reload if navigating by fragment within
1996 // the same URL, but do reload if going to a new URL or to the same URL with no
1997 // fragment identifier at all."
beidson@apple.comee497252009-08-10 16:35:00 +00001998 if (!destinationURL.hasFragmentIdentifier())
darinc370e7e2006-11-08 05:52:27 +00001999 return true;
beidson@apple.comee497252009-08-10 16:35:00 +00002000 return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
darinc370e7e2006-11-08 05:52:27 +00002001}
2002
2003void FrameLoader::closeOldDataSources()
2004{
2005 // FIXME: Is it important for this traversal to be postorder instead of preorder?
2006 // If so, add helpers for postorder traversal, and use them. If not, then lets not
2007 // use a recursive algorithm here.
darin@apple.comfed4d162013-08-25 02:28:06 +00002008 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().nextSibling())
andersca@apple.comdf550b92013-08-15 22:17:17 +00002009 child->loader().closeOldDataSources();
darinc370e7e2006-11-08 05:52:27 +00002010
2011 if (m_documentLoader)
akling@apple.com7f50aae2013-08-22 16:01:31 +00002012 m_client.dispatchWillClose();
darinc370e7e2006-11-08 05:52:27 +00002013
akling@apple.com7f50aae2013-08-22 16:01:31 +00002014 m_client.setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
darinc370e7e2006-11-08 05:52:27 +00002015}
2016
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00002017void FrameLoader::prepareForCachedPageRestore()
darinc370e7e2006-11-08 05:52:27 +00002018{
darin@apple.comfed4d162013-08-25 02:28:06 +00002019 ASSERT(!m_frame.tree().parent());
akling@apple.com7f50aae2013-08-22 16:01:31 +00002020 ASSERT(m_frame.page());
darin@apple.com0e83ab12013-09-28 17:19:04 +00002021 ASSERT(m_frame.isMainFrame());
darinc370e7e2006-11-08 05:52:27 +00002022
akling@apple.com7f50aae2013-08-22 16:01:31 +00002023 m_frame.navigationScheduler().cancel();
darinc370e7e2006-11-08 05:52:27 +00002024
2025 // We still have to close the previous part page.
2026 closeURL();
darinc370e7e2006-11-08 05:52:27 +00002027
2028 // Delete old status bar messages (if it _was_ activated on last URL).
akling@apple.com7f50aae2013-08-22 16:01:31 +00002029 if (m_frame.script().canExecuteScripts(NotAboutToExecuteScript)) {
2030 DOMWindow* window = m_frame.document()->domWindow();
abarth@webkit.org13fe1e22012-08-16 22:29:48 +00002031 window->setStatus(String());
2032 window->setDefaultStatus(String());
darinc370e7e2006-11-08 05:52:27 +00002033 }
beidson@apple.com028c7a72009-02-11 22:01:22 +00002034}
2035
beidson@apple.com913c7f82009-09-02 20:16:38 +00002036void FrameLoader::open(CachedFrameBase& cachedFrame)
beidson@apple.com028c7a72009-02-11 22:01:22 +00002037{
2038 m_isComplete = false;
2039
2040 // Don't re-emit the load event.
2041 m_didCallImplicitClose = true;
2042
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002043 URL url = cachedFrame.url();
darinc370e7e2006-11-08 05:52:27 +00002044
abarth@webkit.org55d49da2011-06-20 23:32:54 +00002045 // FIXME: I suspect this block of code doesn't do anything.
benjamin@webkit.orgf726d632012-03-04 03:26:27 +00002046 if (url.protocolIsInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
weinig@apple.comc5002662007-12-12 07:26:19 +00002047 url.setPath("/");
abarth@webkit.org55d49da2011-06-20 23:32:54 +00002048
abarth@webkit.org91289c32010-04-12 04:54:55 +00002049 started();
beidson@apple.com028c7a72009-02-11 22:01:22 +00002050 Document* document = cachedFrame.document();
beidson50c3bd82007-01-03 03:11:18 +00002051 ASSERT(document);
abarth@webkit.org23ea90a2012-08-14 19:47:59 +00002052 ASSERT(document->domWindow());
2053
2054 clear(document, true, true, cachedFrame.isMainFrame());
2055
darinc370e7e2006-11-08 05:52:27 +00002056 document->setInPageCache(false);
2057
2058 m_needsClear = true;
2059 m_isComplete = false;
ggarena57755c2007-07-09 21:08:10 +00002060 m_didCallImplicitClose = false;
weinig@apple.comc5002662007-12-12 07:26:19 +00002061 m_outgoingReferrer = url.string();
kmccullo6b1b5c22007-05-24 20:06:56 +00002062
beidson@apple.com028c7a72009-02-11 22:01:22 +00002063 FrameView* view = cachedFrame.view();
2064
2065 // When navigating to a CachedFrame its FrameView should never be null. If it is we'll crash in creative ways downstream.
2066 ASSERT(view);
beidson@apple.com24f92a52009-09-03 00:07:51 +00002067 view->setWasScrolledByUser(false);
adachan@apple.com95f492a2009-08-24 19:55:23 +00002068
cdumez@apple.com665ca3b2015-05-08 18:15:57 +00002069 Optional<IntRect> previousViewFrameRect = m_frame.view() ? m_frame.view()->frameRect() : Optional<IntRect>(Nullopt);
akling@apple.com7f50aae2013-08-22 16:01:31 +00002070 m_frame.setView(view);
cdumez@apple.com665ca3b2015-05-08 18:15:57 +00002071
2072 // Use the previous ScrollView's frame rect.
2073 if (previousViewFrameRect)
2074 view->setFrameRect(previousViewFrameRect.value());
darinc370e7e2006-11-08 05:52:27 +00002075
akling@apple.com7f50aae2013-08-22 16:01:31 +00002076 m_frame.setDocument(document);
abarth@webkit.org23ea90a2012-08-14 19:47:59 +00002077 document->domWindow()->resumeFromPageCache();
weinig@apple.com5367c412008-06-27 00:03:25 +00002078
abarth@webkit.org622d9df2009-05-22 16:44:47 +00002079 updateFirstPartyForCookies();
darinc370e7e2006-11-08 05:52:27 +00002080
beidson@apple.com028c7a72009-02-11 22:01:22 +00002081 cachedFrame.restore();
darinc370e7e2006-11-08 05:52:27 +00002082}
2083
darinc370e7e2006-11-08 05:52:27 +00002084bool FrameLoader::isHostedByObjectElement() const
2085{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002086 HTMLFrameOwnerElement* owner = m_frame.ownerElement();
darinc370e7e2006-11-08 05:52:27 +00002087 return owner && owner->hasTagName(objectTag);
2088}
2089
darinc370e7e2006-11-08 05:52:27 +00002090bool FrameLoader::isReplacing() const
2091{
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002092 return m_loadType == FrameLoadType::Replace;
darinc370e7e2006-11-08 05:52:27 +00002093}
2094
2095void FrameLoader::setReplacing()
2096{
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002097 m_loadType = FrameLoadType::Replace;
darinc370e7e2006-11-08 05:52:27 +00002098}
2099
darinc370e7e2006-11-08 05:52:27 +00002100bool FrameLoader::subframeIsLoading() const
2101{
2102 // 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 +00002103 for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling()) {
andersca@apple.comdf550b92013-08-15 22:17:17 +00002104 FrameLoader& childLoader = child->loader();
2105 DocumentLoader* documentLoader = childLoader.documentLoader();
darinc370e7e2006-11-08 05:52:27 +00002106 if (documentLoader && documentLoader->isLoadingInAPISense())
2107 return true;
andersca@apple.comdf550b92013-08-15 22:17:17 +00002108 documentLoader = childLoader.provisionalDocumentLoader();
darinc370e7e2006-11-08 05:52:27 +00002109 if (documentLoader && documentLoader->isLoadingInAPISense())
2110 return true;
andersca@apple.comdf550b92013-08-15 22:17:17 +00002111 documentLoader = childLoader.policyDocumentLoader();
mjs@apple.com17a175d2010-07-18 00:15:31 +00002112 if (documentLoader)
2113 return true;
darinc370e7e2006-11-08 05:52:27 +00002114 }
2115 return false;
2116}
2117
2118void FrameLoader::willChangeTitle(DocumentLoader* loader)
2119{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002120 m_client.willChangeTitle(loader);
darinc370e7e2006-11-08 05:52:27 +00002121}
2122
2123FrameLoadType FrameLoader::loadType() const
2124{
2125 return m_loadType;
2126}
antti@apple.com4da613e2008-12-15 15:28:41 +00002127
beidson@apple.comee54c992009-05-19 23:41:15 +00002128CachePolicy FrameLoader::subresourceCachePolicy() const
antti@apple.com4da613e2008-12-15 15:28:41 +00002129{
2130 if (m_isComplete)
2131 return CachePolicyVerify;
ap@webkit.org86b10982009-05-18 15:30:10 +00002132
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002133 if (m_loadType == FrameLoadType::ReloadFromOrigin)
antti@apple.com4da613e2008-12-15 15:28:41 +00002134 return CachePolicyReload;
ap@webkit.org86b10982009-05-18 15:30:10 +00002135
darin@apple.comfed4d162013-08-25 02:28:06 +00002136 if (Frame* parentFrame = m_frame.tree().parent()) {
andersca@apple.comdf550b92013-08-15 22:17:17 +00002137 CachePolicy parentCachePolicy = parentFrame->loader().subresourceCachePolicy();
antti@apple.com4da613e2008-12-15 15:28:41 +00002138 if (parentCachePolicy != CachePolicyVerify)
2139 return parentCachePolicy;
2140 }
slewis@apple.comef236f42011-05-25 23:00:45 +00002141
cdumez@apple.com74493162014-12-08 18:42:12 +00002142 switch (m_loadType) {
2143 case FrameLoadType::Reload:
antti@apple.com4da613e2008-12-15 15:28:41 +00002144 return CachePolicyRevalidate;
cdumez@apple.com74493162014-12-08 18:42:12 +00002145 case FrameLoadType::Back:
2146 case FrameLoadType::Forward:
2147 case FrameLoadType::IndexedBackForward:
joepeck@webkit.org853e6862010-11-18 17:59:53 +00002148 return CachePolicyHistoryBuffer;
cdumez@apple.com74493162014-12-08 18:42:12 +00002149 case FrameLoadType::ReloadFromOrigin:
2150 ASSERT_NOT_REACHED(); // Already handled above.
2151 return CachePolicyReload;
2152 case FrameLoadType::RedirectWithLockedBackForwardList:
2153 case FrameLoadType::Replace:
2154 case FrameLoadType::Same:
2155 case FrameLoadType::Standard:
2156 return CachePolicyVerify;
2157 }
ossy@webkit.org41788ca2014-12-08 19:30:19 +00002158
2159 RELEASE_ASSERT_NOT_REACHED();
2160 return CachePolicyVerify;
antti@apple.com4da613e2008-12-15 15:28:41 +00002161}
darinc370e7e2006-11-08 05:52:27 +00002162
andersca4422e372007-01-12 19:56:19 +00002163void FrameLoader::checkLoadCompleteForThisFrame()
2164{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002165 ASSERT(m_client.hasWebView());
andersca4422e372007-01-12 19:56:19 +00002166
2167 switch (m_state) {
2168 case FrameStateProvisional: {
mitz@apple.com6699e272015-05-01 23:47:03 +00002169 if (!m_provisionalLoadErrorBeingHandledURL.isEmpty())
andersca4422e372007-01-12 19:56:19 +00002170 return;
2171
2172 RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
2173 if (!pdl)
2174 return;
2175
2176 // If we've received any errors we may be stuck in the provisional state and actually complete.
2177 const ResourceError& error = pdl->mainDocumentError();
2178 if (error.isNull())
2179 return;
2180
2181 // Check all children first.
2182 RefPtr<HistoryItem> item;
akling@apple.com7f50aae2013-08-22 16:01:31 +00002183 if (Page* page = m_frame.page())
commit-queue@webkit.org21a48d82011-01-09 01:27:19 +00002184 if (isBackForwardLoadType(loadType()))
2185 // Reset the back forward list to the last committed history item at the top level.
akling@apple.com095b5442013-08-27 02:47:37 +00002186 item = page->mainFrame().loader().history().currentItem();
andersca4422e372007-01-12 19:56:19 +00002187
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00002188 // Only reset if we aren't already going to a new provisional item.
akling@apple.com672cb852013-08-22 20:27:27 +00002189 bool shouldReset = !history().provisionalItem();
ap@apple.com421e9a12011-03-24 00:50:45 +00002190 if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
mitz@apple.com6699e272015-05-01 23:47:03 +00002191 m_provisionalLoadErrorBeingHandledURL = m_provisionalDocumentLoader->url();
akling@apple.com7f50aae2013-08-22 16:01:31 +00002192 m_client.dispatchDidFailProvisionalLoad(error);
mitz@apple.com6699e272015-05-01 23:47:03 +00002193 m_provisionalLoadErrorBeingHandledURL = { };
andersca4422e372007-01-12 19:56:19 +00002194
ap@apple.com09535d12011-03-24 00:48:30 +00002195 ASSERT(!pdl->isLoading());
andersca4422e372007-01-12 19:56:19 +00002196
eric@webkit.orgb562c402010-01-13 01:29:35 +00002197 // If we're in the middle of loading multipart data, we need to restore the document loader.
2198 if (isReplacing() && !m_documentLoader.get())
eric@webkit.org90747252010-01-12 18:10:14 +00002199 setDocumentLoader(m_provisionalDocumentLoader.get());
2200
andersca4422e372007-01-12 19:56:19 +00002201 // Finish resetting the load state, but only if another load hasn't been started by the
2202 // delegate callback.
2203 if (pdl == m_provisionalDocumentLoader)
2204 clearProvisionalLoad();
tonikitoo@webkit.orge94ac9b2009-11-16 15:38:19 +00002205 else if (activeDocumentLoader()) {
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002206 URL unreachableURL = activeDocumentLoader()->unreachableURL();
andersca4422e372007-01-12 19:56:19 +00002207 if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
2208 shouldReset = false;
2209 }
2210 }
darine0cef432007-07-10 19:21:23 +00002211 if (shouldReset && item)
akling@apple.com7f50aae2013-08-22 16:01:31 +00002212 if (Page* page = m_frame.page()) {
akling@apple.com31cf0092013-09-11 15:24:45 +00002213 page->backForward().setCurrentItem(item.get());
akling@apple.com7f50aae2013-08-22 16:01:31 +00002214 m_frame.loader().client().updateGlobalHistoryItemForPage();
mitz@apple.combc843762008-12-08 21:18:11 +00002215 }
andersca4422e372007-01-12 19:56:19 +00002216 return;
2217 }
2218
2219 case FrameStateCommittedPage: {
2220 DocumentLoader* dl = m_documentLoader.get();
darin@apple.com40b5df62009-05-02 19:58:43 +00002221 if (!dl || (dl->isLoadingInAPISense() && !dl->isStopping()))
andersca4422e372007-01-12 19:56:19 +00002222 return;
2223
darin@apple.comaf8b1a92011-06-25 00:09:37 +00002224 setState(FrameStateComplete);
andersca4422e372007-01-12 19:56:19 +00002225
2226 // FIXME: Is this subsequent work important if we already navigated away?
2227 // Maybe there are bugs because of that, or extra work we can skip because
2228 // the new page is ready.
2229
akling@apple.com7f50aae2013-08-22 16:01:31 +00002230 m_client.forceLayoutForNonHTML();
andersca4422e372007-01-12 19:56:19 +00002231
2232 // If the user had a scroll point, scroll to it, overriding the anchor point if any.
akling@apple.com7f50aae2013-08-22 16:01:31 +00002233 if (m_frame.page()) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002234 if (isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadType::Reload || m_loadType == FrameLoadType::ReloadFromOrigin)
akling@apple.com672cb852013-08-22 20:27:27 +00002235 history().restoreScrollPositionAndViewState();
darin@apple.come10e1282010-10-30 00:44:33 +00002236 }
andersca4422e372007-01-12 19:56:19 +00002237
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00002238 if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
mjs8d620d52007-05-10 12:31:42 +00002239 return;
2240
timothy_horton@apple.com346f8d72013-08-01 00:06:51 +00002241 m_progressTracker->progressCompleted();
eric.carlson@apple.com77b4a112014-10-30 19:04:29 +00002242 Page* page = m_frame.page();
2243 if (page) {
darin@apple.com0e83ab12013-09-28 17:19:04 +00002244 if (m_frame.isMainFrame())
timothy_horton@apple.com346f8d72013-08-01 00:06:51 +00002245 page->resetRelevantPaintedObjectCounter();
andersca@apple.com7c0a3fc2012-05-01 22:22:25 +00002246 }
2247
andersca4422e372007-01-12 19:56:19 +00002248 const ResourceError& error = dl->mainDocumentError();
mario@webkit.org685258f2011-12-06 00:10:55 +00002249
2250 AXObjectCache::AXLoadingEvent loadingEvent;
2251 if (!error.isNull()) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00002252 m_client.dispatchDidFailLoad(error);
mario@webkit.org685258f2011-12-06 00:10:55 +00002253 loadingEvent = AXObjectCache::AXLoadingFailed;
2254 } else {
akling@apple.com7f50aae2013-08-22 16:01:31 +00002255 m_client.dispatchDidFinishLoad();
mario@webkit.org685258f2011-12-06 00:10:55 +00002256 loadingEvent = AXObjectCache::AXLoadingFinished;
2257 }
2258
2259 // Notify accessibility.
akling@apple.com7f50aae2013-08-22 16:01:31 +00002260 if (AXObjectCache* cache = m_frame.document()->existingAXObjectCache())
2261 cache->frameLoadingEventNotification(&m_frame, loadingEvent);
andersca4422e372007-01-12 19:56:19 +00002262
beidson@apple.com4aecb3d2015-07-09 04:47:09 +00002263 // The above calls to dispatchDidFinishLoad() might have detached the Frame
2264 // from its Page and also might have caused Page to be deleted.
2265 // Don't assume 'page' is still available to use.
2266 if (m_frame.isMainFrame() && m_frame.page()) {
2267 ASSERT(&m_frame.page()->mainFrame() == &m_frame);
2268 m_frame.page()->mainFrame().diagnosticLoggingClient().logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageLoadedKey(), emptyString(), error.isNull() ? DiagnosticLoggingResultPass : DiagnosticLoggingResultFail, ShouldSample::Yes);
2269 }
eric.carlson@apple.com77b4a112014-10-30 19:04:29 +00002270
andersca4422e372007-01-12 19:56:19 +00002271 return;
2272 }
2273
2274 case FrameStateComplete:
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002275 m_loadType = FrameLoadType::Standard;
beidson@apple.comd1418272009-01-30 17:30:47 +00002276 frameLoadCompleted();
andersca4422e372007-01-12 19:56:19 +00002277 return;
2278 }
2279
2280 ASSERT_NOT_REACHED();
2281}
andersca5d5f8022007-02-28 00:38:00 +00002282
abarth@webkit.org453854e2009-10-08 03:17:08 +00002283void FrameLoader::continueLoadAfterWillSubmitForm()
darinc370e7e2006-11-08 05:52:27 +00002284{
beidsonb72fe2e2007-05-03 21:35:24 +00002285 if (!m_provisionalDocumentLoader)
2286 return;
2287
japhet@chromium.org91e5e2f2012-04-02 22:08:19 +00002288 prepareForLoadStart();
beidson@apple.com1289cdb2008-07-03 06:10:47 +00002289
2290 // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
2291 // so we need to null check it again.
2292 if (!m_provisionalDocumentLoader)
2293 return;
beidsonb72fe2e2007-05-03 21:35:24 +00002294
2295 DocumentLoader* activeDocLoader = activeDocumentLoader();
2296 if (activeDocLoader && activeDocLoader->isLoadingMainResource())
2297 return;
2298
beidson@apple.comac095c02009-08-18 01:37:56 +00002299 m_loadingFromCachedPage = false;
japhet@chromium.orgd7b5ad22012-03-27 20:30:28 +00002300 m_provisionalDocumentLoader->startLoadingMainResource();
darinc370e7e2006-11-08 05:52:27 +00002301}
darinc370e7e2006-11-08 05:52:27 +00002302
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002303static URL originatingURLFromBackForwardList(Page* page)
ap@apple.com456d4652011-11-30 12:13:31 +00002304{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002305 // FIXME: Can this logic be replaced with m_frame.document()->firstPartyForCookies()?
ap@apple.com456d4652011-11-30 12:13:31 +00002306 // It has the same meaning of "page a user thinks is the current one".
2307
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002308 URL originalURL;
akling@apple.com31cf0092013-09-11 15:24:45 +00002309 int backCount = page->backForward().backCount();
ap@apple.com456d4652011-11-30 12:13:31 +00002310 for (int backIndex = 0; backIndex <= backCount; backIndex++) {
2311 // FIXME: At one point we had code here to check a "was user gesture" flag.
2312 // Do we need to restore that logic?
akling@apple.com31cf0092013-09-11 15:24:45 +00002313 HistoryItem* historyItem = page->backForward().itemAtIndex(-backIndex);
ap@apple.com456d4652011-11-30 12:13:31 +00002314 if (!historyItem)
2315 continue;
2316
2317 originalURL = historyItem->originalURL();
2318 if (!originalURL.isNull())
2319 return originalURL;
2320 }
2321
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002322 return URL();
ap@apple.com456d4652011-11-30 12:13:31 +00002323}
2324
2325void FrameLoader::setOriginalURLForDownloadRequest(ResourceRequest& request)
2326{
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002327 URL originalURL;
ap@apple.com456d4652011-11-30 12:13:31 +00002328
2329 // If there is no referrer, assume that the download was initiated directly, so current document is
2330 // completely unrelated to it. See <rdar://problem/5294691>.
2331 // FIXME: Referrer is not sent in many other cases, so we will often miss this important information.
2332 // Find a better way to decide whether the download was unrelated to current document.
2333 if (!request.httpReferrer().isNull()) {
2334 // find the first item in the history that was originated by the user
akling@apple.com7f50aae2013-08-22 16:01:31 +00002335 originalURL = originatingURLFromBackForwardList(m_frame.page());
ap@apple.com456d4652011-11-30 12:13:31 +00002336 }
2337
2338 if (originalURL.isNull())
2339 originalURL = request.url();
2340
2341 if (!originalURL.protocol().isEmpty() && !originalURL.host().isEmpty()) {
2342 unsigned port = originalURL.port();
2343
2344 // Original URL is needed to show the user where a file was downloaded from. We should make a URL that won't result in downloading the file again.
2345 // FIXME: Using host-only URL is a very heavy-handed approach. We should attempt to provide the actual page where the download was initiated from, as a reminder to the user.
2346 String hostOnlyURLString;
2347 if (port)
commit-queue@webkit.org9ca94b02014-08-30 23:19:32 +00002348 hostOnlyURLString = makeString(originalURL.protocol(), "://", originalURL.host(), ':', String::number(port));
ap@apple.com456d4652011-11-30 12:13:31 +00002349 else
2350 hostOnlyURLString = makeString(originalURL.protocol(), "://", originalURL.host());
2351
2352 // FIXME: Rename firstPartyForCookies back to mainDocumentURL. It was a mistake to think that it was only used for cookies.
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002353 request.setFirstPartyForCookies(URL(URL(), hostOnlyURLString));
ap@apple.com456d4652011-11-30 12:13:31 +00002354 }
2355}
2356
bdakin@apple.com0b27e9a2012-09-25 20:01:33 +00002357void FrameLoader::didLayout(LayoutMilestones milestones)
darinc370e7e2006-11-08 05:52:27 +00002358{
darin@apple.com0e83ab12013-09-28 17:19:04 +00002359 ASSERT(m_frame.isMainFrame());
bdakin@apple.com7ce7e1b2013-08-12 21:37:06 +00002360
akling@apple.com7f50aae2013-08-22 16:01:31 +00002361 m_client.dispatchDidLayout(milestones);
bdakin@apple.com3ab37372012-02-01 21:52:41 +00002362}
2363
bdakin@apple.come98caf12012-09-25 23:08:03 +00002364void FrameLoader::didFirstLayout()
2365{
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00002366#if PLATFORM(IOS)
2367 // Only send layout-related delegate callbacks synchronously for the main frame to
2368 // avoid reentering layout for the main frame while delivering a layout-related delegate
2369 // callback for a subframe.
2370 if (&m_frame != &m_frame.page()->mainFrame())
2371 return;
2372#endif
akling@apple.com7f50aae2013-08-22 16:01:31 +00002373 if (m_frame.page() && isBackForwardLoadType(m_loadType))
akling@apple.com672cb852013-08-22 20:27:27 +00002374 history().restoreScrollPositionAndViewState();
bdakin@apple.come98caf12012-09-25 23:08:03 +00002375
2376 if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2377 m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
2378}
2379
darinc370e7e2006-11-08 05:52:27 +00002380void FrameLoader::frameLoadCompleted()
2381{
beidson@apple.comd1418272009-01-30 17:30:47 +00002382 // Note: Can be called multiple times.
2383
akling@apple.com7f50aae2013-08-22 16:01:31 +00002384 m_client.frameLoadCompleted();
darinc370e7e2006-11-08 05:52:27 +00002385
akling@apple.com672cb852013-08-22 20:27:27 +00002386 history().updateForFrameLoadCompleted();
beidson@apple.comd1418272009-01-30 17:30:47 +00002387
darinc370e7e2006-11-08 05:52:27 +00002388 // After a canceled provisional load, firstLayoutDone is false.
2389 // Reset it to true if we're displaying a page.
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00002390 if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
2391 m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
darinc370e7e2006-11-08 05:52:27 +00002392}
2393
darinc370e7e2006-11-08 05:52:27 +00002394void FrameLoader::detachChildren()
2395{
akling@apple.com72c1c362013-09-06 01:34:05 +00002396 Vector<Ref<Frame>, 16> childrenToDetach;
2397 childrenToDetach.reserveInitialCapacity(m_frame.tree().childCount());
darin@apple.comfed4d162013-08-25 02:28:06 +00002398 for (Frame* child = m_frame.tree().lastChild(); child; child = child->tree().previousSibling())
akling@apple.com72c1c362013-09-06 01:34:05 +00002399 childrenToDetach.uncheckedAppend(*child);
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00002400 for (auto& child : childrenToDetach)
2401 child->loader().detachFromParent();
darinc370e7e2006-11-08 05:52:27 +00002402}
2403
beidson@apple.com028c7a72009-02-11 22:01:22 +00002404void FrameLoader::closeAndRemoveChild(Frame* child)
2405{
darin@apple.comfed4d162013-08-25 02:28:06 +00002406 child->tree().detachFromParent();
beidson@apple.com028c7a72009-02-11 22:01:22 +00002407
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002408 child->setView(nullptr);
beidson@apple.com24f92a52009-09-03 00:07:51 +00002409 if (child->ownerElement() && child->page())
simon.fraser@apple.com940f2fe2012-09-26 21:13:38 +00002410 child->page()->decrementSubframeCount();
kkristof@inf.u-szeged.hu8c9862d2012-06-01 13:51:14 +00002411 child->willDetachPage();
abarth@webkit.org047b8772012-02-22 02:22:15 +00002412 child->detachFromPage();
beidson@apple.com028c7a72009-02-11 22:01:22 +00002413
darin@apple.comfed4d162013-08-25 02:28:06 +00002414 m_frame.tree().removeChild(child);
beidson@apple.com028c7a72009-02-11 22:01:22 +00002415}
2416
darin@apple.comaf8b1a92011-06-25 00:09:37 +00002417// Called every time a resource is completely loaded or an error is received.
darinc370e7e2006-11-08 05:52:27 +00002418void FrameLoader::checkLoadComplete()
2419{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002420 ASSERT(m_client.hasWebView());
anderscaa315d572007-03-13 01:09:53 +00002421
darin@apple.comf53381b2009-09-23 23:27:01 +00002422 m_shouldCallCheckLoadComplete = false;
2423
akling@apple.com72c1c362013-09-06 01:34:05 +00002424 if (!m_frame.page())
2425 return;
2426
anderscaa315d572007-03-13 01:09:53 +00002427 // FIXME: Always traversing the entire frame tree is a bit inefficient, but
2428 // is currently needed in order to null out the previous history item for all frames.
akling@apple.com72c1c362013-09-06 01:34:05 +00002429 Vector<Ref<Frame>, 16> frames;
darin@apple.com0e83ab12013-09-28 17:19:04 +00002430 for (Frame* frame = &m_frame.mainFrame(); frame; frame = frame->tree().traverseNext())
akling@apple.com72c1c362013-09-06 01:34:05 +00002431 frames.append(*frame);
2432
2433 // To process children before their parents, iterate the vector backwards.
2434 for (unsigned i = frames.size(); i; --i)
2435 frames[i - 1]->loader().checkLoadCompleteForThisFrame();
darinc370e7e2006-11-08 05:52:27 +00002436}
2437
2438int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
2439{
2440 if (!recurse)
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +00002441 return m_frame.document()->cachedResourceLoader().requestCount();
darinc370e7e2006-11-08 05:52:27 +00002442
2443 int count = 0;
darin@apple.comfed4d162013-08-25 02:28:06 +00002444 for (Frame* frame = &m_frame; frame; frame = frame->tree().traverseNext(&m_frame))
cdumez@apple.com0bb03ec2015-01-28 05:53:53 +00002445 count += frame->document()->cachedResourceLoader().requestCount();
darinc370e7e2006-11-08 05:52:27 +00002446 return count;
2447}
2448
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002449String FrameLoader::userAgent(const URL& url) const
darinc370e7e2006-11-08 05:52:27 +00002450{
seokju@webkit.orgcb8504d2014-01-09 17:19:34 +00002451 return m_client.userAgent(url);
darinc370e7e2006-11-08 05:52:27 +00002452}
2453
darinc370e7e2006-11-08 05:52:27 +00002454void FrameLoader::handledOnloadEvents()
2455{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002456 m_client.dispatchDidHandleOnloadEvents();
japhet@chromium.org92a952b2010-07-12 18:14:17 +00002457
darin@apple.comaf8b1a92011-06-25 00:09:37 +00002458 if (documentLoader())
commit-queue@webkit.org2ca2f772010-08-17 23:40:00 +00002459 documentLoader()->handledOnloadEvents();
darinc370e7e2006-11-08 05:52:27 +00002460}
2461
2462void FrameLoader::frameDetached()
2463{
2464 stopAllLoaders();
akling@apple.com7f50aae2013-08-22 16:01:31 +00002465 m_frame.document()->stopActiveDOMObjects();
darinc370e7e2006-11-08 05:52:27 +00002466 detachFromParent();
2467}
2468
ggarenc04b2c52006-11-30 21:06:14 +00002469void FrameLoader::detachFromParent()
darinc370e7e2006-11-08 05:52:27 +00002470{
akling@apple.coma34e5222013-09-10 03:44:05 +00002471 Ref<Frame> protect(m_frame);
ggarenc04b2c52006-11-30 21:06:14 +00002472
ggarenacf28742006-12-27 07:38:18 +00002473 closeURL();
akling@apple.com672cb852013-08-22 20:27:27 +00002474 history().saveScrollPositionAndViewStateToItem(history().currentItem());
ggarenc04b2c52006-11-30 21:06:14 +00002475 detachChildren();
japhet@chromium.org7d4347c2010-11-03 19:04:41 +00002476 // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren()
2477 // will trigger the unload event handlers of any child frames, and those event
2478 // handlers might start a new subresource load in this frame.
2479 stopAllLoaders();
arobendfc56662007-06-21 01:37:24 +00002480
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00002481 InspectorInstrumentation::frameDetachedFromParent(m_frame);
arobendfc56662007-06-21 01:37:24 +00002482
beidson@apple.com24f92a52009-09-03 00:07:51 +00002483 detachViewsAndDocumentLoader();
2484
weinig@apple.comeefc25d2013-11-08 22:42:27 +00002485 m_progressTracker = nullptr;
japhet@chromium.org7879dd72012-08-30 02:58:37 +00002486
darin@apple.comfed4d162013-08-25 02:28:06 +00002487 if (Frame* parent = m_frame.tree().parent()) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00002488 parent->loader().closeAndRemoveChild(&m_frame);
andersca@apple.comdf550b92013-08-15 22:17:17 +00002489 parent->loader().scheduleCheckCompleted();
weinigc34c71c2007-03-09 16:05:37 +00002490 } else {
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002491 m_frame.setView(nullptr);
akling@apple.com7f50aae2013-08-22 16:01:31 +00002492 m_frame.willDetachPage();
2493 m_frame.detachFromPage();
ddkilzer3adeb2f2006-12-28 23:33:37 +00002494 }
ggarenc04b2c52006-11-30 21:06:14 +00002495}
beidson@apple.com24f92a52009-09-03 00:07:51 +00002496
2497void FrameLoader::detachViewsAndDocumentLoader()
2498{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002499 m_client.detachedFromParent2();
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002500 setDocumentLoader(nullptr);
akling@apple.com7f50aae2013-08-22 16:01:31 +00002501 m_client.detachedFromParent3();
beidson@apple.com24f92a52009-09-03 00:07:51 +00002502}
antti@apple.com4da613e2008-12-15 15:28:41 +00002503
2504void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
2505{
jochen@chromium.orgdac140c2011-08-01 21:18:49 +00002506 addExtraFieldsToRequest(request, m_loadType, false);
antti@apple.com4da613e2008-12-15 15:28:41 +00002507}
darinc370e7e2006-11-08 05:52:27 +00002508
antti@apple.com4da613e2008-12-15 15:28:41 +00002509void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
2510{
ap@apple.com8d5f01b2013-01-07 18:40:55 +00002511 // FIXME: Using m_loadType seems wrong for some callers.
2512 // If we are only preparing to load the main resource, that is previous load's load type!
jochen@chromium.orgdac140c2011-08-01 21:18:49 +00002513 addExtraFieldsToRequest(request, m_loadType, true);
antti@apple.com4da613e2008-12-15 15:28:41 +00002514}
2515
jochen@chromium.orgdac140c2011-08-01 21:18:49 +00002516void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource)
beidson50c3bd82007-01-03 03:11:18 +00002517{
beidson@apple.com341a3d82009-03-03 19:08:56 +00002518 // Don't set the cookie policy URL if it's already been set.
ap@apple.com8d5f01b2013-01-07 18:40:55 +00002519 // But make sure to set it on all requests regardless of protocol, as it has significance beyond the cookie policy (<rdar://problem/6616664>).
abarth@webkit.org622d9df2009-05-22 16:44:47 +00002520 if (request.firstPartyForCookies().isEmpty()) {
darin@apple.com0e83ab12013-09-28 17:19:04 +00002521 if (mainResource && m_frame.isMainFrame())
abarth@webkit.org622d9df2009-05-22 16:44:47 +00002522 request.setFirstPartyForCookies(request.url());
akling@apple.com7f50aae2013-08-22 16:01:31 +00002523 else if (Document* document = m_frame.document())
abarth@webkit.org622d9df2009-05-22 16:44:47 +00002524 request.setFirstPartyForCookies(document->firstPartyForCookies());
beidson@apple.com341a3d82009-03-03 19:08:56 +00002525 }
abarth@webkit.org622d9df2009-05-22 16:44:47 +00002526
beidson@apple.com341a3d82009-03-03 19:08:56 +00002527 // The remaining modifications are only necessary for HTTP and HTTPS.
benjamin@webkit.orgf726d632012-03-04 03:26:27 +00002528 if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
hyatt@apple.com0c933b82009-02-03 23:56:06 +00002529 return;
2530
beidson50c3bd82007-01-03 03:11:18 +00002531 applyUserAgent(request);
ap@apple.com8d5f01b2013-01-07 18:40:55 +00002532
japhet@chromium.orgf00dffa2010-07-16 07:46:22 +00002533 if (!mainResource) {
2534 if (request.isConditional())
2535 request.setCachePolicy(ReloadIgnoringCacheData);
ap@apple.com8d5f01b2013-01-07 18:40:55 +00002536 else if (documentLoader()->isLoadingInAPISense()) {
2537 // If we inherit cache policy from a main resource, we use the DocumentLoader's
2538 // original request cache policy for two reasons:
2539 // 1. For POST requests, we mutate the cache policy for the main resource,
2540 // but we do not want this to apply to subresources
2541 // 2. Delegates that modify the cache policy using willSendRequest: should
2542 // not affect any other resources. Such changes need to be done
2543 // per request.
2544 ResourceRequestCachePolicy mainDocumentOriginalCachePolicy = documentLoader()->originalRequest().cachePolicy();
2545 // 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.
2546 // This policy is set on initial request too, but should not be inherited.
2547 ResourceRequestCachePolicy subresourceCachePolicy = (mainDocumentOriginalCachePolicy == ReturnCacheDataDontLoad) ? ReturnCacheDataElseLoad : mainDocumentOriginalCachePolicy;
2548 request.setCachePolicy(subresourceCachePolicy);
2549 } else
japhet@chromium.orgf00dffa2010-07-16 07:46:22 +00002550 request.setCachePolicy(UseProtocolCachePolicy);
ap@apple.com8d5f01b2013-01-07 18:40:55 +00002551
2552 // FIXME: Other FrameLoader functions have duplicated code for setting cache policy of main request when reloading.
2553 // It seems better to manage it explicitly than to hide the logic inside addExtraFieldsToRequest().
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002554 } else if (loadType == FrameLoadType::Reload || loadType == FrameLoadType::ReloadFromOrigin || request.isConditional())
japhet@chromium.org92a952b2010-07-12 18:14:17 +00002555 request.setCachePolicy(ReloadIgnoringCacheData);
ap@apple.com8d5f01b2013-01-07 18:40:55 +00002556
antti@apple.com7c97e2c2015-03-19 05:21:40 +00002557 if (m_overrideCachePolicyForTesting)
2558 request.setCachePolicy(m_overrideCachePolicyForTesting.value());
antti@apple.com1229ead2015-03-30 21:09:14 +00002559 if (m_overrideResourceLoadPriorityForTesting)
2560 request.setPriority(m_overrideResourceLoadPriorityForTesting.value());
antti@apple.com7c97e2c2015-03-19 05:21:40 +00002561
japhet@chromium.org1e313142010-08-31 22:53:31 +00002562 if (request.cachePolicy() == ReloadIgnoringCacheData) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002563 if (loadType == FrameLoadType::Reload)
andersca@apple.coma96cf712014-06-14 17:49:44 +00002564 request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002565 else if (loadType == FrameLoadType::ReloadFromOrigin) {
andersca@apple.coma96cf712014-06-14 17:49:44 +00002566 request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache");
2567 request.setHTTPHeaderField(HTTPHeaderName::Pragma, "no-cache");
japhet@chromium.org1e313142010-08-31 22:53:31 +00002568 }
2569 }
beidson50c3bd82007-01-03 03:11:18 +00002570
beidson50c3bd82007-01-03 03:11:18 +00002571 if (mainResource)
staikos@webkit.org159f11f2009-05-18 23:48:30 +00002572 request.setHTTPAccept(defaultAcceptHeader);
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002573
2574 // Make sure we send the Origin header.
2575 addHTTPOriginIfNeeded(request, String());
ap@webkit.org113cb8c2008-12-05 14:43:53 +00002576
ap@apple.com9454f7c2013-06-20 20:06:02 +00002577 // Only set fallback array if it's still empty (later attempts may be incorrect, see bug 117818).
2578 if (request.responseContentDispositionEncodingFallbackArray().isEmpty()) {
2579 // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
akling@apple.com7f50aae2013-08-22 16:01:31 +00002580 request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_frame.document()->encoding(), m_frame.settings().defaultTextEncodingName());
ap@apple.com9454f7c2013-06-20 20:06:02 +00002581 }
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002582}
2583
tony@chromium.orgc1443b72011-06-24 22:05:16 +00002584void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin)
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002585{
2586 if (!request.httpOrigin().isEmpty())
2587 return; // Request already has an Origin header.
2588
2589 // Don't send an Origin header for GET or HEAD to avoid privacy issues.
2590 // For example, if an intranet page has a hyperlink to an external web
2591 // site, we don't want to include the Origin of the request because it
2592 // will leak the internal host name. Similar privacy concerns have lead
2593 // to the widespread suppression of the Referer header at the network
2594 // layer.
2595 if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
2596 return;
2597
2598 // For non-GET and non-HEAD methods, always send an Origin header so the
2599 // server knows we support this feature.
2600
2601 if (origin.isEmpty()) {
2602 // If we don't know what origin header to attach, we attach the value
2603 // for an empty origin.
abarth@webkit.org29f0c1a2011-11-05 01:32:07 +00002604 request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
tony@chromium.orgc1443b72011-06-24 22:05:16 +00002605 return;
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002606 }
2607
2608 request.setHTTPOrigin(origin);
beidson50c3bd82007-01-03 03:11:18 +00002609}
2610
beidson@apple.comdab05722015-05-31 05:53:06 +00002611void FrameLoader::loadPostRequest(const FrameLoadRequest& request, const String& referrer, FrameLoadType loadType, Event* event, PassRefPtr<FormState> prpFormState)
anderscade5715d2007-01-06 00:55:49 +00002612{
mrowe@apple.com713db2e2008-07-27 03:49:29 +00002613 RefPtr<FormState> formState = prpFormState;
2614
beidson@apple.combd66a782015-05-29 16:31:49 +00002615 String frameName = request.frameName();
2616 LockHistory lockHistory = request.lockHistory();
2617 AllowNavigationToInvalidURL allowNavigationToInvalidURL = request.allowNavigationToInvalidURL();
2618 NewFrameOpenerPolicy openerPolicy = request.newFrameOpenerPolicy();
2619
2620 const ResourceRequest& inRequest = request.resourceRequest();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002621 const URL& url = inRequest.url();
mrowe@apple.com713db2e2008-07-27 03:49:29 +00002622 RefPtr<FormData> formData = inRequest.httpBody();
2623 const String& contentType = inRequest.httpContentType();
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002624 String origin = inRequest.httpOrigin();
mrowe@apple.com713db2e2008-07-27 03:49:29 +00002625
2626 ResourceRequest workingResourceRequest(url);
anderscade5715d2007-01-06 00:55:49 +00002627
2628 if (!referrer.isEmpty())
mrowe@apple.com713db2e2008-07-27 03:49:29 +00002629 workingResourceRequest.setHTTPReferrer(referrer);
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002630 workingResourceRequest.setHTTPOrigin(origin);
mrowe@apple.com713db2e2008-07-27 03:49:29 +00002631 workingResourceRequest.setHTTPMethod("POST");
2632 workingResourceRequest.setHTTPBody(formData);
2633 workingResourceRequest.setHTTPContentType(contentType);
jochen@chromium.orgdac140c2011-08-01 21:18:49 +00002634 addExtraFieldsToRequest(workingResourceRequest, loadType, true);
anderscade5715d2007-01-06 00:55:49 +00002635
beidson@apple.com87dc6312015-06-02 18:43:13 +00002636 NavigationAction action(workingResourceRequest, loadType, true, event, request.shouldOpenExternalURLsPolicy());
anderscade5715d2007-01-06 00:55:49 +00002637
anderscade5715d2007-01-06 00:55:49 +00002638 if (!frameName.isEmpty()) {
darin@apple.com0f88bda2009-04-02 00:30:50 +00002639 // The search for a target frame is done earlier in the case of form submission.
andersca@apple.com096333f2013-11-07 21:37:36 +00002640 if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName)) {
aestes@apple.com47ac5e12014-08-18 17:48:48 +00002641 targetFrame->loader().loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release(), allowNavigationToInvalidURL);
andersca@apple.com096333f2013-11-07 21:37:36 +00002642 return;
darin@chromium.org1e25ab72012-04-02 20:14:07 +00002643 }
andersca@apple.com096333f2013-11-07 21:37:36 +00002644
ap@apple.coma383f252015-02-14 18:16:00 +00002645 policyChecker().checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName, [this, allowNavigationToInvalidURL, openerPolicy](const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue) {
2646 continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue, allowNavigationToInvalidURL, openerPolicy);
andersca@apple.com096333f2013-11-07 21:37:36 +00002647 });
2648 return;
2649 }
2650
2651 // must grab this now, since this load may stop the previous load and clear this flag
2652 bool isRedirect = m_quickRedirectComing;
aestes@apple.com47ac5e12014-08-18 17:48:48 +00002653 loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release(), allowNavigationToInvalidURL);
andersca@apple.com096333f2013-11-07 21:37:36 +00002654 if (isRedirect) {
2655 m_quickRedirectComing = false;
2656 if (m_provisionalDocumentLoader)
2657 m_provisionalDocumentLoader->setIsClientRedirect(true);
darin@chromium.org1e25ab72012-04-02 20:14:07 +00002658 }
anderscade5715d2007-01-06 00:55:49 +00002659}
2660
youenn.fablet@crf.canon.fr0aef67f2015-04-29 08:18:10 +00002661unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ClientCredentialPolicy clientCredentialPolicy, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
anderscade5715d2007-01-06 00:55:49 +00002662{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002663 ASSERT(m_frame.document());
2664 String referrer = SecurityPolicy::generateReferrerHeader(m_frame.document()->referrerPolicy(), request.url(), outgoingReferrer());
anderscade5715d2007-01-06 00:55:49 +00002665
2666 ResourceRequest initialRequest = request;
2667 initialRequest.setTimeoutInterval(10);
2668
anderscade5715d2007-01-06 00:55:49 +00002669 if (!referrer.isEmpty())
2670 initialRequest.setHTTPReferrer(referrer);
abarth@webkit.orgfb074382008-10-05 19:12:30 +00002671 addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
darine0cef432007-07-10 19:21:23 +00002672
darin@apple.com0e83ab12013-09-28 17:19:04 +00002673 initialRequest.setFirstPartyForCookies(m_frame.mainFrame().loader().documentLoader()->request().url());
japhet@chromium.org92a952b2010-07-12 18:14:17 +00002674
2675 addExtraFieldsToSubresourceRequest(initialRequest);
darine0cef432007-07-10 19:21:23 +00002676
anderscaec429f52007-01-13 01:44:24 +00002677 unsigned long identifier = 0;
anderscade5715d2007-01-06 00:55:49 +00002678 ResourceRequest newRequest(initialRequest);
2679 requestFromDelegate(newRequest, identifier, error);
2680
beidson@apple.come3ea01d2015-07-02 18:33:23 +00002681#if ENABLE(CONTENT_EXTENSIONS)
2682 if (error.isNull()) {
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +00002683 if (auto* page = m_frame.page()) {
2684 if (auto* controller = page->userContentController()) {
2685 if (m_documentLoader && controller->processContentExtensionRulesForLoad(newRequest, ResourceType::Raw, *m_documentLoader) == ContentExtensions::BlockedStatus::Blocked) {
2686 newRequest = { };
2687 error = ResourceError(errorDomainWebKitInternal, 0, initialRequest.url().string(), emptyString());
2688 response = { };
2689 data = nullptr;
2690 }
beidson@apple.come3ea01d2015-07-02 18:33:23 +00002691 }
2692 }
beidson@apple.come3ea01d2015-07-02 18:33:23 +00002693 }
2694#endif
2695
anderscade5715d2007-01-06 00:55:49 +00002696 if (error.isNull()) {
2697 ASSERT(!newRequest.isNull());
youenn.fablet@crf.canon.fr0aef67f2015-04-29 08:18:10 +00002698
darin@chromium.org6042aea2009-07-30 23:08:33 +00002699 if (!documentLoader()->applicationCacheHost()->maybeLoadSynchronously(newRequest, error, response, data)) {
youenn.fablet@crf.canon.fr0aef67f2015-04-29 08:18:10 +00002700 Vector<char> buffer;
2701 platformStrategies()->loaderStrategy()->loadResourceSynchronously(networkingContext(), identifier, newRequest, storedCredentials, clientCredentialPolicy, error, response, buffer);
2702 data = SharedBuffer::adoptVector(buffer);
darin@chromium.org6042aea2009-07-30 23:08:33 +00002703 documentLoader()->applicationCacheHost()->maybeLoadFallbackSynchronously(newRequest, error, response, data);
ap@webkit.orgfb96f8a2009-01-02 09:25:02 +00002704 }
anderscade5715d2007-01-06 00:55:49 +00002705 }
youenn.fablet@crf.canon.fr0aef67f2015-04-29 08:18:10 +00002706 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 +00002707 return identifier;
anderscade5715d2007-01-06 00:55:49 +00002708}
2709
anderscade5715d2007-01-06 00:55:49 +00002710const ResourceRequest& FrameLoader::originalRequest() const
2711{
2712 return activeDocumentLoader()->originalRequestCopy();
2713}
2714
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00002715void FrameLoader::receivedMainResourceError(const ResourceError& error)
anderscade5715d2007-01-06 00:55:49 +00002716{
2717 // Retain because the stop may release the last reference to it.
akling@apple.comf8515982013-09-02 18:50:01 +00002718 Ref<Frame> protect(m_frame);
anderscade5715d2007-01-06 00:55:49 +00002719
2720 RefPtr<DocumentLoader> loader = activeDocumentLoader();
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00002721 // FIXME: Don't want to do this if an entirely new load is going, so should check
2722 // that both data sources on the frame are either this or nil.
2723 stop();
akling@apple.com7f50aae2013-08-22 16:01:31 +00002724 if (m_client.shouldFallBack(error))
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00002725 handleFallbackContent();
abarth@webkit.org1c893f42009-10-10 02:27:21 +00002726
lars8bf288d2007-10-04 08:45:12 +00002727 if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
darin@apple.com4cd1b242009-03-27 23:37:46 +00002728 if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002729 m_submittedFormURL = URL();
anttiac25cb42007-03-02 07:59:15 +00002730
anderscade5715d2007-01-06 00:55:49 +00002731 // We might have made a page cache item, but now we're bailing out due to an error before we ever
2732 // transitioned to the new page (before WebFrameState == commit). The goal here is to restore any state
2733 // so that the existing view (that wenever got far enough to replace) can continue being used.
akling@apple.com672cb852013-08-22 20:27:27 +00002734 history().invalidateCurrentItemCachedPage();
anderscade5715d2007-01-06 00:55:49 +00002735
2736 // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
2737 // status has changed, if there was a redirect. The frame load delegate may have saved some state about
2738 // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
2739 // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
2740 // has ended.
2741 if (m_sentRedirectNotification)
2742 clientRedirectCancelledOrFinished(false);
2743 }
abarth@webkit.org1c893f42009-10-10 02:27:21 +00002744
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00002745 checkCompleted();
akling@apple.com7f50aae2013-08-22 16:01:31 +00002746 if (m_frame.page())
japhet@chromium.org7f7bee42012-03-29 23:17:09 +00002747 checkLoadComplete();
anderscade5715d2007-01-06 00:55:49 +00002748}
2749
anderscade5715d2007-01-06 00:55:49 +00002750void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
2751{
anderscade5715d2007-01-06 00:55:49 +00002752 m_quickRedirectComing = false;
darin4e5519d2007-01-22 02:46:06 +00002753
2754 if (!shouldContinue)
2755 return;
2756
mihaip@chromium.orgd5123ba2011-09-16 02:16:46 +00002757 // If we have a provisional request for a different document, a fragment scroll should cancel it.
2758 if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
2759 m_provisionalDocumentLoader->stopLoading();
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002760 setProvisionalDocumentLoader(nullptr);
mihaip@chromium.orgd5123ba2011-09-16 02:16:46 +00002761 }
2762
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002763 bool isRedirect = m_quickRedirectComing || policyChecker().loadType() == FrameLoadType::RedirectWithLockedBackForwardList;
beidson@apple.com08c61752009-12-03 19:04:40 +00002764 loadInSameDocument(request.url(), 0, !isRedirect);
anderscade5715d2007-01-06 00:55:49 +00002765}
2766
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002767bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const URL& url)
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00002768{
yael.aharon@nokia.com79f69052010-12-30 19:31:00 +00002769 // 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 +00002770 // currently displaying a frameset, or if the URL does not have a fragment.
2771 // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
2772
2773 // FIXME: What about load types other than Standard and Reload?
2774
yael.aharon@nokia.com79f69052010-12-30 19:31:00 +00002775 return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET"))
andersca@apple.comb50fcc32014-06-19 00:13:20 +00002776 && loadType != FrameLoadType::Reload
2777 && loadType != FrameLoadType::ReloadFromOrigin
2778 && loadType != FrameLoadType::Same
akling@apple.com7f50aae2013-08-22 16:01:31 +00002779 && !shouldReload(m_frame.document()->url(), url)
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00002780 // We don't want to just scroll if a link from within a
2781 // frameset is trying to reload the frameset into _top.
akling@apple.com7f50aae2013-08-22 16:01:31 +00002782 && !m_frame.document()->isFrameSet();
ddkilzer@apple.com8c272a82008-07-12 21:33:52 +00002783}
2784
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002785void FrameLoader::scrollToFragmentWithParentBoundary(const URL& url)
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00002786{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002787 FrameView* view = m_frame.view();
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00002788 if (!view)
2789 return;
2790
2791 // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
akling@apple.com7f50aae2013-08-22 16:01:31 +00002792 RefPtr<Frame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame.document()->findUnsafeParentScrollPropagationBoundary() : 0);
tsepez@chromium.org8d3c2c12012-04-17 19:03:42 +00002793
2794 if (boundaryFrame)
2795 boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00002796
2797 view->scrollToFragment(url);
tsepez@chromium.org8d3c2c12012-04-17 19:03:42 +00002798
2799 if (boundaryFrame)
2800 boundaryFrame->view()->setSafeToPropagateScrollToParent(true);
tsepez@chromium.orgf8960562012-04-06 22:15:02 +00002801}
2802
beidson@apple.com7617ce72010-05-13 20:31:46 +00002803bool FrameLoader::shouldClose()
2804{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002805 Page* page = m_frame.page();
akling@apple.combd774812013-05-17 00:03:01 +00002806 if (!page)
2807 return true;
2808 if (!page->chrome().canRunBeforeUnloadConfirmPanel())
beidson@apple.com7617ce72010-05-13 20:31:46 +00002809 return true;
2810
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00002811 // Store all references to each subframe in advance since beforeunload's event handler may modify frame
akling@apple.com72c1c362013-09-06 01:34:05 +00002812 Vector<Ref<Frame>, 16> targetFrames;
2813 targetFrames.append(m_frame);
darin@apple.comfed4d162013-08-25 02:28:06 +00002814 for (Frame* child = m_frame.tree().firstChild(); child; child = child->tree().traverseNext(&m_frame))
akling@apple.com72c1c362013-09-06 01:34:05 +00002815 targetFrames.append(*child);
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00002816
2817 bool shouldClose = false;
2818 {
2819 NavigationDisablerForBeforeUnload navigationDisabler;
2820 size_t i;
2821
2822 for (i = 0; i < targetFrames.size(); i++) {
darin@apple.comfed4d162013-08-25 02:28:06 +00002823 if (!targetFrames[i]->tree().isDescendantOf(&m_frame))
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00002824 continue;
andersca@apple.comdf550b92013-08-15 22:17:17 +00002825 if (!targetFrames[i]->loader().handleBeforeUnloadEvent(page->chrome(), this))
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00002826 break;
2827 }
2828
2829 if (i == targetFrames.size())
2830 shouldClose = true;
2831 }
2832
aestes@apple.comc7f17612011-08-12 19:56:56 +00002833 if (!shouldClose)
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00002834 m_submittedFormURL = URL();
aestes@apple.comc7f17612011-08-12 19:56:56 +00002835
beidson@apple.com1390a812013-07-20 06:43:51 +00002836 m_currentNavigationHasShownBeforeUnloadConfirmPanel = false;
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00002837 return shouldClose;
2838}
2839
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00002840void FrameLoader::handleUnloadEvents(UnloadEventPolicy unloadEventPolicy)
2841{
2842 if (!m_frame.document())
2843 return;
2844
2845 // We store the frame's page in a local variable because the frame might get detached inside dispatchEvent.
2846 ForbidPromptsScope forbidPrompts(m_frame.page());
2847
2848 if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
2849 auto* currentFocusedElement = m_frame.document()->focusedElement();
2850 if (is<HTMLInputElement>(currentFocusedElement))
2851 downcast<HTMLInputElement>(*currentFocusedElement).endEditing();
2852 if (m_pageDismissalEventBeingDispatched == PageDismissalType::None) {
2853 if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
2854 m_pageDismissalEventBeingDispatched = PageDismissalType::PageHide;
2855 m_frame.document()->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame.document()->inPageCache()), m_frame.document());
2856 }
2857
2858 // FIXME: update Page Visibility state here.
2859 // https://bugs.webkit.org/show_bug.cgi?id=116770
2860
2861 if (!m_frame.document()->inPageCache()) {
2862 RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
2863 // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
2864 // while dispatching the event, so protect it to prevent writing the end
2865 // time into freed memory.
2866 RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
2867 m_pageDismissalEventBeingDispatched = PageDismissalType::Unload;
2868 if (documentLoader && documentLoader->timing().navigationStart() && !documentLoader->timing().unloadEventStart() && !documentLoader->timing().unloadEventEnd()) {
2869 auto& timing = documentLoader->timing();
2870 timing.markUnloadEventStart();
2871 m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
2872 timing.markUnloadEventEnd();
2873 } else
2874 m_frame.document()->domWindow()->dispatchEvent(unloadEvent, m_frame.document());
2875 }
2876 }
2877 m_pageDismissalEventBeingDispatched = PageDismissalType::None;
2878 if (m_frame.document())
2879 m_frame.document()->updateStyleIfNeeded();
2880 m_wasUnloadEventEmitted = true;
2881 }
2882
2883 // Dispatching the unload event could have made m_frame.document() null.
2884 if (!m_frame.document())
2885 return;
2886
2887 if (m_frame.document()->inPageCache())
2888 return;
2889
2890 // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
2891 bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
2892 && m_frame.document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
2893
2894 if (!keepEventListeners)
2895 m_frame.document()->removeAllEventListeners();
2896}
2897
beidson@apple.com1390a812013-07-20 06:43:51 +00002898bool FrameLoader::handleBeforeUnloadEvent(Chrome& chrome, FrameLoader* frameLoaderBeingNavigated)
rniwa@webkit.orgcf460072011-01-08 02:15:10 +00002899{
akling@apple.com7f50aae2013-08-22 16:01:31 +00002900 DOMWindow* domWindow = m_frame.document()->domWindow();
beidson@apple.com7617ce72010-05-13 20:31:46 +00002901 if (!domWindow)
2902 return true;
2903
akling@apple.com7f50aae2013-08-22 16:01:31 +00002904 RefPtr<Document> document = m_frame.document();
cdumez@apple.comf9780832015-01-27 00:26:21 +00002905 if (!document->bodyOrFrameset())
beidson@apple.com7617ce72010-05-13 20:31:46 +00002906 return true;
beidson@apple.com1390a812013-07-20 06:43:51 +00002907
beidson@apple.com7617ce72010-05-13 20:31:46 +00002908 RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
cdumez@apple.com83847a92015-06-26 18:26:19 +00002909 m_pageDismissalEventBeingDispatched = PageDismissalType::BeforeUnload;
beidson@apple.com1390a812013-07-20 06:43:51 +00002910
ggaren@apple.comfe41e1b2015-11-10 22:19:44 +00002911 {
2912 ForbidPromptsScope forbidPrompts(m_frame.page());
2913 domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document());
2914 }
beidson@apple.com1390a812013-07-20 06:43:51 +00002915
cdumez@apple.com83847a92015-06-26 18:26:19 +00002916 m_pageDismissalEventBeingDispatched = PageDismissalType::None;
beidson@apple.com7617ce72010-05-13 20:31:46 +00002917
2918 if (!beforeUnloadEvent->defaultPrevented())
2919 document->defaultEventHandler(beforeUnloadEvent.get());
ch.dumez@sisa.samsung.com231386f2013-09-09 18:40:04 +00002920 if (beforeUnloadEvent->returnValue().isNull())
beidson@apple.com7617ce72010-05-13 20:31:46 +00002921 return true;
2922
beidson@apple.com1390a812013-07-20 06:43:51 +00002923 // If the navigating FrameLoader has already shown a beforeunload confirmation panel for the current navigation attempt,
2924 // this frame is not allowed to cause another one to be shown.
2925 if (frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel) {
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00002926 document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Blocked attempt to show multiple beforeunload confirmation dialogs for the same navigation."));
beidson@apple.com1390a812013-07-20 06:43:51 +00002927 return true;
2928 }
2929
2930 // We should only display the beforeunload dialog for an iframe if its SecurityOrigin matches all
2931 // ancestor frame SecurityOrigins up through the navigating FrameLoader.
2932 if (frameLoaderBeingNavigated != this) {
darin@apple.comfed4d162013-08-25 02:28:06 +00002933 Frame* parentFrame = m_frame.tree().parent();
beidson@apple.com1390a812013-07-20 06:43:51 +00002934 while (parentFrame) {
2935 Document* parentDocument = parentFrame->document();
2936 if (!parentDocument)
2937 return true;
akling@apple.com7f50aae2013-08-22 16:01:31 +00002938 if (!m_frame.document() || !m_frame.document()->securityOrigin()->canAccess(parentDocument->securityOrigin())) {
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00002939 document->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Blocked attempt to show beforeunload confirmation dialog on behalf of a frame with different security origin. Protocols, domains, and ports must match."));
beidson@apple.com1390a812013-07-20 06:43:51 +00002940 return true;
2941 }
2942
andersca@apple.comdf550b92013-08-15 22:17:17 +00002943 if (&parentFrame->loader() == frameLoaderBeingNavigated)
beidson@apple.com1390a812013-07-20 06:43:51 +00002944 break;
2945
darin@apple.comfed4d162013-08-25 02:28:06 +00002946 parentFrame = parentFrame->tree().parent();
beidson@apple.com1390a812013-07-20 06:43:51 +00002947 }
2948
2949 // The navigatingFrameLoader should always be in our ancestory.
2950 ASSERT(parentFrame);
andersca@apple.comdf550b92013-08-15 22:17:17 +00002951 ASSERT(&parentFrame->loader() == frameLoaderBeingNavigated);
beidson@apple.com1390a812013-07-20 06:43:51 +00002952 }
2953
2954 frameLoaderBeingNavigated->m_currentNavigationHasShownBeforeUnloadConfirmPanel = true;
2955
ch.dumez@sisa.samsung.com231386f2013-09-09 18:40:04 +00002956 String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->returnValue());
akling@apple.com7f50aae2013-08-22 16:01:31 +00002957 return chrome.runBeforeUnloadConfirmPanel(text, &m_frame);
beidson@apple.com7617ce72010-05-13 20:31:46 +00002958}
2959
aestes@apple.com47ac5e12014-08-18 17:48:48 +00002960void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL)
anderscade5715d2007-01-06 00:55:49 +00002961{
2962 // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
2963 // nil policyDataSource because loading the alternate page will have passed
2964 // through this method already, nested; otherwise, policyDataSource should still be set.
2965 ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
2966
akling@apple.com672cb852013-08-22 20:27:27 +00002967 bool isTargetItem = history().provisionalItem() ? history().provisionalItem()->isTargetItem() : false;
anderscade5715d2007-01-06 00:55:49 +00002968
aestes@apple.com47ac5e12014-08-18 17:48:48 +00002969 bool urlIsDisallowed = allowNavigationToInvalidURL == AllowNavigationToInvalidURL::No && !request.url().isValid();
2970
2971 // Three reasons we can't continue:
anderscade5715d2007-01-06 00:55:49 +00002972 // 1) Navigation policy delegate said we can't so request is nil. A primary case of this
2973 // is the user responding Cancel to the form repost nag sheet.
2974 // 2) User responded Cancel to an alert popped up by the before unload event handler.
aestes@apple.com47ac5e12014-08-18 17:48:48 +00002975 // 3) The request's URL is invalid and navigation to invalid URLs is disallowed.
2976 bool canContinue = shouldContinue && shouldClose() && !urlIsDisallowed;
anderscade5715d2007-01-06 00:55:49 +00002977
2978 if (!canContinue) {
2979 // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we
2980 // need to report that the client redirect was cancelled.
aestes@apple.com47ac5e12014-08-18 17:48:48 +00002981 // FIXME: The client should be told about ignored non-quick redirects, too.
anderscade5715d2007-01-06 00:55:49 +00002982 if (m_quickRedirectComing)
2983 clientRedirectCancelledOrFinished(false);
2984
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00002985 setPolicyDocumentLoader(nullptr);
anderscade5715d2007-01-06 00:55:49 +00002986
2987 // If the navigation request came from the back/forward menu, and we punt on it, we have the
2988 // problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
2989 // we only do this when punting a navigation for the target frame or top-level frame.
darin@apple.com0e83ab12013-09-28 17:19:04 +00002990 if ((isTargetItem || m_frame.isMainFrame()) && isBackForwardLoadType(policyChecker().loadType())) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00002991 if (Page* page = m_frame.page()) {
darin@apple.com0e83ab12013-09-28 17:19:04 +00002992 if (HistoryItem* resetItem = m_frame.mainFrame().loader().history().currentItem()) {
akling@apple.com31cf0092013-09-11 15:24:45 +00002993 page->backForward().setCurrentItem(resetItem);
akling@apple.com7f50aae2013-08-22 16:01:31 +00002994 m_frame.loader().client().updateGlobalHistoryItemForPage();
mitz@apple.combc843762008-12-08 21:18:11 +00002995 }
darine0cef432007-07-10 19:21:23 +00002996 }
andersca@apple.comb85d6742011-03-04 03:21:07 +00002997 }
anderscade5715d2007-01-06 00:55:49 +00002998 return;
2999 }
3000
akling@apple.com24f4d6c2013-09-08 08:17:10 +00003001 FrameLoadType type = policyChecker().loadType();
commit-queue@webkit.org987fd772011-01-21 18:26:42 +00003002 // A new navigation is in progress, so don't clear the history's provisional item.
commit-queue@webkit.orgfc5833b2011-02-23 06:58:46 +00003003 stopAllLoaders(ShouldNotClearProvisionalItem);
beidson@apple.comc90a4422008-10-09 20:43:24 +00003004
3005 // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
3006 // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
akling@apple.com7f50aae2013-08-22 16:01:31 +00003007 if (!m_frame.page())
beidson@apple.comc90a4422008-10-09 20:43:24 +00003008 return;
timothy@apple.com8f207342009-04-11 05:31:05 +00003009
anderscade5715d2007-01-06 00:55:49 +00003010 setProvisionalDocumentLoader(m_policyDocumentLoader.get());
3011 m_loadType = type;
3012 setState(FrameStateProvisional);
3013
hs85.jeong@samsung.com13179142015-10-21 02:12:32 +00003014 setPolicyDocumentLoader(nullptr);
anderscade5715d2007-01-06 00:55:49 +00003015
cdumez@apple.com25743772015-08-17 22:57:27 +00003016 if (isBackForwardLoadType(type)) {
3017 auto& diagnosticLoggingClient = m_frame.mainFrame().diagnosticLoggingClient();
3018 if (history().provisionalItem()->isInPageCache()) {
3019 diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultPass, ShouldSample::Yes);
3020 loadProvisionalItemFromCachedPage();
3021 return;
3022 }
3023 diagnosticLoggingClient.logDiagnosticMessageWithResult(DiagnosticLoggingKeys::pageCacheKey(), DiagnosticLoggingKeys::retrievalKey(), DiagnosticLoggingResultFail, ShouldSample::Yes);
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003024 }
anderscade5715d2007-01-06 00:55:49 +00003025
andersca@apple.com61e33322013-10-05 04:52:04 +00003026 if (!formState) {
beidsonb72fe2e2007-05-03 21:35:24 +00003027 continueLoadAfterWillSubmitForm();
andersca@apple.com61e33322013-10-05 04:52:04 +00003028 return;
3029 }
3030
3031 m_client.dispatchWillSubmitForm(formState, [this](PolicyAction action) {
3032 policyChecker().continueLoadAfterWillSubmitForm(action);
3033 });
anderscade5715d2007-01-06 00:55:49 +00003034}
3035
anderscade5715d2007-01-06 00:55:49 +00003036void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
ap@apple.coma383f252015-02-14 18:16:00 +00003037 PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue, AllowNavigationToInvalidURL allowNavigationToInvalidURL, NewFrameOpenerPolicy openerPolicy)
anderscade5715d2007-01-06 00:55:49 +00003038{
3039 if (!shouldContinue)
3040 return;
3041
akling@apple.com55cde012013-10-05 00:35:12 +00003042 Ref<Frame> frame(m_frame);
akling@apple.com7f50aae2013-08-22 16:01:31 +00003043 RefPtr<Frame> mainFrame = m_client.dispatchCreatePage(action);
anderscade5715d2007-01-06 00:55:49 +00003044 if (!mainFrame)
3045 return;
3046
mjsc946c5e2007-01-31 05:45:47 +00003047 if (frameName != "_blank")
darin@apple.comfed4d162013-08-25 02:28:06 +00003048 mainFrame->tree().setName(frameName);
kmccullo1f901212007-05-16 20:57:47 +00003049
eric@webkit.org5aee6762009-10-06 18:20:33 +00003050 mainFrame->page()->setOpenedByDOM();
akling@apple.com7f50aae2013-08-22 16:01:31 +00003051 mainFrame->loader().m_client.dispatchShow();
ap@apple.coma383f252015-02-14 18:16:00 +00003052 if (openerPolicy == NewFrameOpenerPolicy::Allow) {
cdumez@apple.com78141732014-11-04 23:00:48 +00003053 mainFrame->loader().setOpener(frame.ptr());
jochen@chromium.org235ee972012-05-09 22:13:12 +00003054 mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy());
3055 }
beidson@apple.com87dc6312015-06-02 18:43:13 +00003056
3057 NavigationAction newAction(request, action.shouldOpenExternalURLsPolicy());
3058 mainFrame->loader().loadWithNavigationAction(request, newAction, LockHistory::No, FrameLoadType::Standard, formState, allowNavigationToInvalidURL);
anderscade5715d2007-01-06 00:55:49 +00003059}
3060
anderscaec429f52007-01-13 01:44:24 +00003061void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
anderscade5715d2007-01-06 00:55:49 +00003062{
3063 ASSERT(!request.isNull());
3064
darine0cef432007-07-10 19:21:23 +00003065 identifier = 0;
akling@apple.com7f50aae2013-08-22 16:01:31 +00003066 if (Page* page = m_frame.page()) {
akling@apple.comeb67e0a2013-08-19 08:24:08 +00003067 identifier = page->progress().createUniqueIdentifier();
akling@apple.com654fd9a2013-10-06 21:07:29 +00003068 notifier().assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
darine0cef432007-07-10 19:21:23 +00003069 }
anderscaec429f52007-01-13 01:44:24 +00003070
anderscade5715d2007-01-06 00:55:49 +00003071 ResourceRequest newRequest(request);
akling@apple.com654fd9a2013-10-06 21:07:29 +00003072 notifier().dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
anderscade5715d2007-01-06 00:55:49 +00003073
3074 if (newRequest.isNull())
weinig@apple.com87a569c2008-05-18 01:21:20 +00003075 error = cancelledError(request);
anderscade5715d2007-01-06 00:55:49 +00003076 else
3077 error = ResourceError();
3078
3079 request = newRequest;
3080}
3081
aestes@apple.com0c8e1912013-04-06 03:09:25 +00003082void FrameLoader::loadedResourceFromMemoryCache(CachedResource* resource, ResourceRequest& newRequest)
anderscade5715d2007-01-06 00:55:49 +00003083{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003084 Page* page = m_frame.page();
darin@apple.com837a78c2009-01-07 15:40:24 +00003085 if (!page)
anderscade5715d2007-01-06 00:55:49 +00003086 return;
3087
japhet@chromium.orgede5cc52012-10-16 19:45:46 +00003088 if (!resource->shouldSendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
darin@apple.com837a78c2009-01-07 15:40:24 +00003089 return;
3090
japhet@chromium.org3e317182013-01-29 20:06:19 +00003091 // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
3092 if (resource->type() == CachedResource::MainResource)
3093 return;
3094
darin@apple.com837a78c2009-01-07 15:40:24 +00003095 if (!page->areMemoryCacheClientCallsEnabled()) {
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003096 InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), resource);
jpfau@apple.com97c6a7f2013-02-26 00:49:17 +00003097 m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->resourceRequest());
darin@apple.com837a78c2009-01-07 15:40:24 +00003098 m_documentLoader->didTellClientAboutLoad(resource->url());
3099 return;
3100 }
3101
akling@apple.com7f50aae2013-08-22 16:01:31 +00003102 if (m_client.dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), newRequest, resource->response(), resource->encodedSize())) {
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003103 InspectorInstrumentation::didLoadResourceFromMemoryCache(*page, m_documentLoader.get(), resource);
darin@apple.com837a78c2009-01-07 15:40:24 +00003104 m_documentLoader->didTellClientAboutLoad(resource->url());
timothy@apple.com8f85dce2008-01-08 23:51:28 +00003105 return;
3106 }
3107
anderscaec429f52007-01-13 01:44:24 +00003108 unsigned long identifier;
anderscade5715d2007-01-06 00:55:49 +00003109 ResourceError error;
aestes@apple.com0c8e1912013-04-06 03:09:25 +00003110 requestFromDelegate(newRequest, identifier, error);
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003111 InspectorInstrumentation::markResourceAsCached(*page, identifier);
akling@apple.com654fd9a2013-10-06 21:07:29 +00003112 notifier().sendRemainingDelegateMessages(m_documentLoader.get(), identifier, newRequest, resource->response(), 0, resource->encodedSize(), 0, error);
anderscade5715d2007-01-06 00:55:49 +00003113}
3114
3115void FrameLoader::applyUserAgent(ResourceRequest& request)
3116{
caseq@chromium.org3d57ec62011-02-04 13:25:42 +00003117 String userAgent = this->userAgent(request.url());
anderscade5715d2007-01-06 00:55:49 +00003118 ASSERT(!userAgent.isNull());
3119 request.setHTTPUserAgent(userAgent);
3120}
3121
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003122bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const URL& url, unsigned long requestIdentifier)
weinig@apple.com5af461c2009-04-08 22:16:23 +00003123{
akling@apple.com52989472013-09-16 20:09:25 +00003124 Frame& topFrame = m_frame.tree().top();
3125 if (&m_frame == &topFrame)
weinig@apple.com5af461c2009-04-08 22:16:23 +00003126 return false;
3127
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003128 XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
3129
3130 switch (disposition) {
3131 case XFrameOptionsSameOrigin: {
weinig@apple.com5af461c2009-04-08 22:16:23 +00003132 RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
akling@apple.com52989472013-09-16 20:09:25 +00003133 if (!origin->isSameSchemeHostPort(topFrame.document()->securityOrigin()))
weinig@apple.com5af461c2009-04-08 22:16:23 +00003134 return true;
darin@apple.comfed4d162013-08-25 02:28:06 +00003135 for (Frame* frame = m_frame.tree().parent(); frame; frame = frame->tree().parent()) {
akling@apple.comfbea4062014-02-27 20:24:03 +00003136 if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin()))
mkwst@chromium.orgf9d8fa02013-03-19 21:12:24 +00003137 break;
mkwst@chromium.orgf9d8fa02013-03-19 21:12:24 +00003138 }
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003139 return false;
weinig@apple.com5af461c2009-04-08 22:16:23 +00003140 }
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003141 case XFrameOptionsDeny:
3142 return true;
3143 case XFrameOptionsAllowAll:
3144 return false;
3145 case XFrameOptionsConflict:
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00003146 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 +00003147 return true;
3148 case XFrameOptionsInvalid:
joepeck@webkit.org1f45df92014-02-06 23:45:53 +00003149 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 +00003150 return false;
psolanki@apple.come2dc3b92014-02-20 18:23:24 +00003151 case XFrameOptionsNone:
mkwst@chromium.org97421c02013-03-28 08:59:00 +00003152 return false;
3153 }
psolanki@apple.come2dc3b92014-02-20 18:23:24 +00003154 ASSERT_NOT_REACHED();
3155 return false;
weinig@apple.com5af461c2009-04-08 22:16:23 +00003156}
3157
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003158void FrameLoader::loadProvisionalItemFromCachedPage()
beidson50c3bd82007-01-03 03:11:18 +00003159{
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003160 DocumentLoader* provisionalLoader = provisionalDocumentLoader();
mkwst@chromium.org6f6d9bc2013-05-30 12:08:58 +00003161 LOG(PageCache, "WebCorePageCache: Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().stringCenterEllipsizedToLength().utf8().data());
beidson@apple.comac095c02009-08-18 01:37:56 +00003162
japhet@chromium.org91e5e2f2012-04-02 22:08:19 +00003163 prepareForLoadStart();
beidson@apple.comac095c02009-08-18 01:37:56 +00003164
3165 m_loadingFromCachedPage = true;
simonjam@chromium.orgdfab5cf2011-12-15 18:45:29 +00003166
eric@webkit.orgf9396152010-08-08 06:19:48 +00003167 // Should have timing data from previous time(s) the page was shown.
akling@apple.com5a7607f2015-01-21 22:33:49 +00003168 ASSERT(provisionalLoader->timing().navigationStart());
eric@webkit.orgf9396152010-08-08 06:19:48 +00003169 provisionalLoader->resetTiming();
akling@apple.com5a7607f2015-01-21 22:33:49 +00003170 provisionalLoader->timing().markNavigationStart();
beidson@apple.comac095c02009-08-18 01:37:56 +00003171
3172 provisionalLoader->setCommitted(true);
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003173 commitProvisionalLoad();
beidson50c3bd82007-01-03 03:11:18 +00003174}
3175
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003176bool FrameLoader::shouldTreatURLAsSameAsCurrent(const URL& url) const
beidson50c3bd82007-01-03 03:11:18 +00003177{
akling@apple.com672cb852013-08-22 20:27:27 +00003178 if (!history().currentItem())
beidson50c3bd82007-01-03 03:11:18 +00003179 return false;
akling@apple.com672cb852013-08-22 20:27:27 +00003180 return url == history().currentItem()->url() || url == history().currentItem()->originalURL();
beidson50c3bd82007-01-03 03:11:18 +00003181}
3182
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003183bool FrameLoader::shouldTreatURLAsSrcdocDocument(const URL& url) const
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00003184{
3185 if (!equalIgnoringCase(url.string(), "about:srcdoc"))
3186 return false;
akling@apple.com7f50aae2013-08-22 16:01:31 +00003187 HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement();
abarth@webkit.orgb2515fa2012-04-04 05:54:26 +00003188 if (!ownerElement)
3189 return false;
3190 if (!ownerElement->hasTagName(iframeTag))
3191 return false;
3192 return ownerElement->fastHasAttribute(srcdocAttr);
3193}
3194
abarth@webkit.orgb46fdef2012-04-13 00:42:37 +00003195Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
weinig@apple.com77427802008-01-11 00:23:13 +00003196{
darin@apple.comfed4d162013-08-25 02:28:06 +00003197 Frame* frame = m_frame.tree().find(name);
abarth@webkit.orgb46fdef2012-04-13 00:42:37 +00003198
ap@apple.comf8c414e2013-08-13 03:44:57 +00003199 // FIXME: Eventually all callers should supply the actual activeDocument so we can call canNavigate with the right document.
3200 if (!activeDocument)
akling@apple.com7f50aae2013-08-22 16:01:31 +00003201 activeDocument = m_frame.document();
ap@apple.comf8c414e2013-08-13 03:44:57 +00003202
3203 if (!activeDocument->canNavigate(frame))
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003204 return nullptr;
abarth@webkit.orgb46fdef2012-04-13 00:42:37 +00003205
darin@apple.com0f88bda2009-04-02 00:30:50 +00003206 return frame;
weinig@apple.com77427802008-01-11 00:23:13 +00003207}
3208
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003209void FrameLoader::loadSameDocumentItem(HistoryItem& item)
beidson@apple.com08c61752009-12-03 19:04:40 +00003210{
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003211 ASSERT(item.documentSequenceNumber() == history().currentItem()->documentSequenceNumber());
beidson@apple.com08c61752009-12-03 19:04:40 +00003212
3213 // Save user view state to the current history item here since we don't do a normal load.
3214 // FIXME: Does form state need to be saved here too?
akling@apple.com672cb852013-08-22 20:27:27 +00003215 history().saveScrollPositionAndViewStateToItem(history().currentItem());
akling@apple.com7f50aae2013-08-22 16:01:31 +00003216 if (FrameView* view = m_frame.view())
beidson@apple.com08c61752009-12-03 19:04:40 +00003217 view->setWasScrolledByUser(false);
3218
beidson@apple.comc16ea842015-07-10 19:01:51 +00003219 history().setCurrentItem(&item);
beidson@apple.com08c61752009-12-03 19:04:40 +00003220
3221 // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003222 loadInSameDocument(item.url(), item.stateObject(), false);
beidson@apple.com08c61752009-12-03 19:04:40 +00003223
3224 // 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 +00003225 history().restoreScrollPositionAndViewState();
beidson@apple.com08c61752009-12-03 19:04:40 +00003226}
3227
abarth@webkit.org1c893f42009-10-10 02:27:21 +00003228// FIXME: This function should really be split into a couple pieces, some of
3229// which should be methods of HistoryController and some of which should be
3230// methods of FrameLoader.
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003231void FrameLoader::loadDifferentDocumentItem(HistoryItem& item, FrameLoadType loadType, FormSubmissionCacheLoadPolicy cacheLoadPolicy)
beidson50c3bd82007-01-03 03:11:18 +00003232{
beidson@apple.com08c61752009-12-03 19:04:40 +00003233 // Remember this item so we can traverse any child items as child frames load
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003234 history().setProvisionalItem(&item);
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003235
cdumez@apple.com4faf1ef2015-01-30 20:49:33 +00003236 if (CachedPage* cachedPage = PageCache::singleton().get(item, m_frame.page())) {
mitz@apple.com4a604422014-11-13 23:22:50 +00003237 auto documentLoader = cachedPage->documentLoader();
cdumez@apple.com6478e4d2015-06-14 04:53:14 +00003238 m_client.updateCachedDocumentLoader(*documentLoader);
mitz@apple.com4a604422014-11-13 23:22:50 +00003239 documentLoader->setTriggeringAction(NavigationAction(documentLoader->request(), loadType, false));
3240 documentLoader->setLastCheckedRequest(ResourceRequest());
3241 loadWithDocumentLoader(documentLoader, loadType, 0, AllowNavigationToInvalidURL::Yes);
japhet@chromium.orgd48109c2010-06-04 17:41:26 +00003242 return;
beidson@apple.com08c61752009-12-03 19:04:40 +00003243 }
adele@apple.comf3d6b892008-04-29 01:30:20 +00003244
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003245 URL itemURL = item.url();
3246 URL itemOriginalURL = item.originalURL();
darin@apple.com5ffbb5c2013-09-27 16:39:41 +00003247 URL currentURL;
beidson0c345992007-02-13 08:59:33 +00003248 if (documentLoader())
weinig@apple.comc5002662007-12-12 07:26:19 +00003249 currentURL = documentLoader()->url();
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003250 RefPtr<FormData> formData = item.formData();
beidson50c3bd82007-01-03 03:11:18 +00003251
beidson@apple.com08c61752009-12-03 19:04:40 +00003252 ResourceRequest request(itemURL);
3253
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003254 if (!item.referrer().isNull())
3255 request.setHTTPReferrer(item.referrer());
dbates@webkit.orgae34b602015-08-05 16:05:55 +00003256
3257 ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(m_frame, item.shouldOpenExternalURLsPolicy());
3258 bool isFormSubmission = false;
3259 Event* event = nullptr;
3260
beidson@apple.com08c61752009-12-03 19:04:40 +00003261 // If this was a repost that failed the page cache, we might try to repost the form.
3262 NavigationAction action;
3263 if (formData) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00003264 formData->generateFiles(m_frame.document());
beidson@apple.com08c61752009-12-03 19:04:40 +00003265
3266 request.setHTTPMethod("POST");
3267 request.setHTTPBody(formData);
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003268 request.setHTTPContentType(item.formContentType());
3269 RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item.referrer());
beidson@apple.com08c61752009-12-03 19:04:40 +00003270 addHTTPOriginIfNeeded(request, securityOrigin->toString());
3271
3272 // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
3273 // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003274 addExtraFieldsToRequest(request, loadType, true);
beidson@apple.com08c61752009-12-03 19:04:40 +00003275
3276 // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
3277 // We want to know this before talking to the policy delegate, since it affects whether
3278 // we show the DoYouReallyWantToRepost nag.
3279 //
3280 // This trick has a small bug (3123893) where we might find a cache hit, but then
3281 // have the item vanish when we try to use it in the ensuing nav. This should be
3282 // extremely rare, but in that case the user will get an error on the navigation.
3283
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003284 if (cacheLoadPolicy == MayAttemptCacheOnlyLoadForFormSubmissionItem) {
3285 request.setCachePolicy(ReturnCacheDataDontLoad);
dbates@webkit.orgae34b602015-08-05 16:05:55 +00003286 action = NavigationAction(request, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy);
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003287 } else {
3288 request.setCachePolicy(ReturnCacheDataElseLoad);
dbates@webkit.orgae34b602015-08-05 16:05:55 +00003289 action = NavigationAction(request, NavigationType::FormResubmitted, event, shouldOpenExternalURLsPolicy);
beidson@apple.com08c61752009-12-03 19:04:40 +00003290 }
3291 } else {
3292 switch (loadType) {
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003293 case FrameLoadType::Reload:
3294 case FrameLoadType::ReloadFromOrigin:
3295 request.setCachePolicy(ReloadIgnoringCacheData);
3296 break;
3297 case FrameLoadType::Back:
3298 case FrameLoadType::Forward:
3299 case FrameLoadType::IndexedBackForward:
cdumez@apple.com49421c92015-03-20 05:45:38 +00003300 request.setCachePolicy(ReturnCacheDataElseLoad);
andersca@apple.comb50fcc32014-06-19 00:13:20 +00003301 break;
3302 case FrameLoadType::Standard:
3303 case FrameLoadType::RedirectWithLockedBackForwardList:
3304 break;
3305 case FrameLoadType::Same:
3306 default:
3307 ASSERT_NOT_REACHED();
beidson@apple.com08c61752009-12-03 19:04:40 +00003308 }
3309
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003310 addExtraFieldsToRequest(request, loadType, true);
beidson@apple.com08c61752009-12-03 19:04:40 +00003311
jochen@chromium.org056b7fa2011-10-18 04:47:05 +00003312 ResourceRequest requestForOriginalURL(request);
3313 requestForOriginalURL.setURL(itemOriginalURL);
dbates@webkit.orgae34b602015-08-05 16:05:55 +00003314 action = NavigationAction(requestForOriginalURL, loadType, isFormSubmission, event, shouldOpenExternalURLsPolicy);
jochen@chromium.org056b7fa2011-10-18 04:47:05 +00003315 }
3316
aestes@apple.com47ac5e12014-08-18 17:48:48 +00003317 loadWithNavigationAction(request, action, LockHistory::No, loadType, 0, AllowNavigationToInvalidURL::Yes);
beidson@apple.com08c61752009-12-03 19:04:40 +00003318}
3319
3320// Loads content into this frame, as specified by history item
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003321void FrameLoader::loadItem(HistoryItem& item, FrameLoadType loadType)
beidson@apple.com08c61752009-12-03 19:04:40 +00003322{
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003323 m_requestedHistoryItem = &item;
akling@apple.com672cb852013-08-22 20:27:27 +00003324 HistoryItem* currentItem = history().currentItem();
cdumez@apple.comfea5cb92015-02-02 00:49:36 +00003325 bool sameDocumentNavigation = currentItem && item.shouldDoSameDocumentNavigationTo(*currentItem);
darin@chromium.orge71dd0f2009-04-17 20:31:17 +00003326
beidson@apple.com08c61752009-12-03 19:04:40 +00003327 if (sameDocumentNavigation)
mihaip@chromium.orge5dbd372010-12-08 02:32:41 +00003328 loadSameDocumentItem(item);
beidson@apple.com08c61752009-12-03 19:04:40 +00003329 else
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003330 loadDifferentDocumentItem(item, loadType, MayAttemptCacheOnlyLoadForFormSubmissionItem);
3331}
3332
3333void FrameLoader::retryAfterFailedCacheOnlyMainResourceLoad()
3334{
3335 ASSERT(m_state == FrameStateProvisional);
3336 ASSERT(!m_loadingFromCachedPage);
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003337 ASSERT(history().provisionalItem());
akling@apple.com672cb852013-08-22 20:27:27 +00003338 ASSERT(history().provisionalItem()->formData());
3339 ASSERT(history().provisionalItem() == m_requestedHistoryItem.get());
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003340
3341 FrameLoadType loadType = m_loadType;
cdumez@apple.com67e10f72015-01-29 18:38:51 +00003342 HistoryItem& item = *history().provisionalItem();
ap@apple.com8d5f01b2013-01-07 18:40:55 +00003343
3344 stopAllLoaders(ShouldNotClearProvisionalItem);
3345 loadDifferentDocumentItem(item, loadType, MayNotAttemptCacheOnlyLoadForFormSubmissionItem);
beidson50c3bd82007-01-03 03:11:18 +00003346}
3347
anderscac8ee2462007-01-05 22:26:32 +00003348ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
3349{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003350 ResourceError error = m_client.cancelledError(request);
weinig@apple.com87a569c2008-05-18 01:21:20 +00003351 error.setIsCancellation(true);
3352 return error;
anderscac8ee2462007-01-05 22:26:32 +00003353}
3354
commit-queue@webkit.org8090ccb2015-10-06 08:18:08 +00003355ResourceError FrameLoader::blockedByContentBlockerError(const ResourceRequest& request) const
3356{
3357 return m_client.blockedByContentBlockerError(request);
3358}
3359
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00003360#if PLATFORM(IOS)
3361RetainPtr<CFDictionaryRef> FrameLoader::connectionProperties(ResourceLoader* loader)
3362{
3363 return m_client.connectionProperties(loader->documentLoader(), loader->identifier());
3364}
3365#endif
3366
andersca4422e372007-01-12 19:56:19 +00003367String FrameLoader::referrer() const
3368{
ap@apple.com9fd20002010-07-01 18:47:57 +00003369 return m_documentLoader ? m_documentLoader->request().httpReferrer() : "";
andersca4422e372007-01-12 19:56:19 +00003370}
3371
aroben@apple.com11dd5262009-11-13 23:49:05 +00003372void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
lars1e1dad32007-01-23 10:28:38 +00003373{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003374 if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript))
thatcher10840e52007-09-22 00:49:09 +00003375 return;
3376
weinig@apple.com8f716032013-10-02 17:03:09 +00003377 Vector<Ref<DOMWrapperWorld>> worlds;
aroben@apple.com11dd5262009-11-13 23:49:05 +00003378 ScriptController::getAllWorlds(worlds);
cdumez@apple.com2f661202014-11-04 07:22:18 +00003379 for (auto& world : worlds)
3380 dispatchDidClearWindowObjectInWorld(world);
aroben@apple.com11dd5262009-11-13 23:49:05 +00003381}
3382
weinig@apple.com8f716032013-10-02 17:03:09 +00003383void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld& world)
aroben@apple.com11dd5262009-11-13 23:49:05 +00003384{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003385 if (!m_frame.script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame.script().existingWindowShell(world))
aroben@apple.com11dd5262009-11-13 23:49:05 +00003386 return;
3387
akling@apple.com7f50aae2013-08-22 16:01:31 +00003388 m_client.dispatchDidClearWindowObjectInWorld(world);
timothy@apple.comefb8ac12008-07-24 02:48:36 +00003389
akling@apple.com7f50aae2013-08-22 16:01:31 +00003390 if (Page* page = m_frame.page())
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003391 page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
loislo@chromium.orge971cb52011-02-08 17:32:44 +00003392
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003393 InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
lars1e1dad32007-01-23 10:28:38 +00003394}
3395
beidson@apple.com2a75a962012-04-24 18:12:55 +00003396void FrameLoader::dispatchGlobalObjectAvailableInAllWorlds()
3397{
weinig@apple.com8f716032013-10-02 17:03:09 +00003398 Vector<Ref<DOMWrapperWorld>> worlds;
beidson@apple.com2a75a962012-04-24 18:12:55 +00003399 ScriptController::getAllWorlds(worlds);
cdumez@apple.com2f661202014-11-04 07:22:18 +00003400 for (auto& world : worlds)
3401 m_client.dispatchGlobalObjectAvailable(world);
beidson@apple.com2a75a962012-04-24 18:12:55 +00003402}
3403
abarth@webkit.org8b45d862011-11-05 21:55:59 +00003404SandboxFlags FrameLoader::effectiveSandboxFlags() const
abarth@webkit.orgb8a10552009-12-02 02:40:35 +00003405{
abarth@webkit.orgf2c54c22010-04-11 06:57:13 +00003406 SandboxFlags flags = m_forcedSandboxFlags;
darin@apple.comfed4d162013-08-25 02:28:06 +00003407 if (Frame* parentFrame = m_frame.tree().parent())
abarth@webkit.org8b45d862011-11-05 21:55:59 +00003408 flags |= parentFrame->document()->sandboxFlags();
akling@apple.com7f50aae2013-08-22 16:01:31 +00003409 if (HTMLFrameOwnerElement* ownerElement = m_frame.ownerElement())
abarth@webkit.orgb8a10552009-12-02 02:40:35 +00003410 flags |= ownerElement->sandboxFlags();
abarth@webkit.org8b45d862011-11-05 21:55:59 +00003411 return flags;
abarth@webkit.orgf5267a42010-01-10 08:14:05 +00003412}
abarth@webkit.orgb8a10552009-12-02 02:40:35 +00003413
lars1e1dad32007-01-23 10:28:38 +00003414void FrameLoader::didChangeTitle(DocumentLoader* loader)
3415{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003416 m_client.didChangeTitle(loader);
lars1e1dad32007-01-23 10:28:38 +00003417
darin@apple.com719d29c2009-07-24 00:09:17 +00003418 if (loader == m_documentLoader) {
lars1e1dad32007-01-23 10:28:38 +00003419 // Must update the entries in the back-forward list too.
akling@apple.com672cb852013-08-22 20:27:27 +00003420 history().setCurrentItemTitle(loader->title());
lars1e1dad32007-01-23 10:28:38 +00003421 // This must go through the WebFrame because it has the right notion of the current b/f item.
akling@apple.com7f50aae2013-08-22 16:01:31 +00003422 m_client.setTitle(loader->title(), loader->urlForHistory());
3423 m_client.setMainFrameDocumentReady(true); // update observers with new DOMDocument
3424 m_client.dispatchDidReceiveTitle(loader->title());
lars1e1dad32007-01-23 10:28:38 +00003425 }
joepeck@webkit.orgd2ecf372013-12-04 18:20:37 +00003426
3427#if ENABLE(REMOTE_INSPECTOR)
3428 if (m_frame.isMainFrame())
3429 m_frame.page()->remoteInspectorInformationDidChange();
3430#endif
lars1e1dad32007-01-23 10:28:38 +00003431}
andersca4422e372007-01-12 19:56:19 +00003432
arobendfc56662007-06-21 01:37:24 +00003433void FrameLoader::dispatchDidCommitLoad()
3434{
japhet@chromium.org61d4b9c2010-06-21 20:06:02 +00003435 if (m_stateMachine.creatingInitialEmptyDocument())
darin@apple.com87134f22007-12-05 22:58:41 +00003436 return;
3437
akling@apple.com7f50aae2013-08-22 16:01:31 +00003438 m_client.dispatchDidCommitLoad();
arobendfc56662007-06-21 01:37:24 +00003439
darin@apple.com0e83ab12013-09-28 17:19:04 +00003440 if (m_frame.isMainFrame()) {
akling@apple.com7f50aae2013-08-22 16:01:31 +00003441 m_frame.page()->resetSeenPlugins();
3442 m_frame.page()->resetSeenMediaEngines();
jer.noble@apple.com2d0a60a2012-10-18 18:12:57 +00003443 }
jer.noble@apple.com381b4672012-07-28 00:41:18 +00003444
burg@cs.washington.edudbacfc12015-01-05 21:30:33 +00003445 InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
commit-queue@webkit.org42b47872013-02-19 19:19:02 +00003446
joepeck@webkit.orgd2ecf372013-12-04 18:20:37 +00003447#if ENABLE(REMOTE_INSPECTOR)
akling@apple.comfbea4062014-02-27 20:24:03 +00003448 if (m_frame.isMainFrame())
joepeck@webkit.orgd2ecf372013-12-04 18:20:37 +00003449 m_frame.page()->remoteInspectorInformationDidChange();
3450#endif
arobendfc56662007-06-21 01:37:24 +00003451}
3452
darin@apple.com837a78c2009-01-07 15:40:24 +00003453void FrameLoader::tellClientAboutPastMemoryCacheLoads()
3454{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003455 ASSERT(m_frame.page());
3456 ASSERT(m_frame.page()->areMemoryCacheClientCallsEnabled());
darin@apple.com837a78c2009-01-07 15:40:24 +00003457
3458 if (!m_documentLoader)
3459 return;
3460
jpfau@apple.com97c6a7f2013-02-26 00:49:17 +00003461 Vector<ResourceRequest> pastLoads;
darin@apple.com837a78c2009-01-07 15:40:24 +00003462 m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
3463
commit-queue@webkit.orgacddfad2015-09-30 05:53:51 +00003464 for (auto& pastLoad : pastLoads) {
3465 CachedResource* resource = MemoryCache::singleton().resourceForRequest(pastLoad, m_frame.page()->sessionID());
darin@apple.com837a78c2009-01-07 15:40:24 +00003466
3467 // FIXME: These loads, loaded from cache, but now gone from the cache by the time
3468 // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
3469 // Consider if there's some efficient way of remembering enough to deliver this client call.
3470 // We have the URL, but not the rest of the response or the length.
3471 if (!resource)
3472 continue;
3473
3474 ResourceRequest request(resource->url());
akling@apple.com7f50aae2013-08-22 16:01:31 +00003475 m_client.dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
darin@apple.com837a78c2009-01-07 15:40:24 +00003476 }
3477}
3478
diegohcg@webkit.org838e0a22010-09-04 14:48:30 +00003479NetworkingContext* FrameLoader::networkingContext() const
3480{
3481 return m_networkingContext.get();
3482}
3483
antti@apple.coma6775c12013-04-05 21:19:56 +00003484void FrameLoader::loadProgressingStatusChanged()
3485{
antti@apple.com08536d12014-06-27 21:58:06 +00003486 if (auto* view = m_frame.mainFrame().view())
3487 view->loadProgressingStatusChanged();
antti@apple.coma6775c12013-04-05 21:19:56 +00003488}
3489
timothy_horton@apple.com88756d62013-05-30 06:24:36 +00003490void FrameLoader::forcePageTransitionIfNeeded()
3491{
akling@apple.com7f50aae2013-08-22 16:01:31 +00003492 m_client.forcePageTransitionIfNeeded();
timothy_horton@apple.com88756d62013-05-30 06:24:36 +00003493}
3494
antti@apple.com1229ead2015-03-30 21:09:14 +00003495void FrameLoader::clearTestingOverrides()
3496{
3497 m_overrideCachePolicyForTesting = Nullopt;
3498 m_overrideResourceLoadPriorityForTesting = Nullopt;
antti@apple.com2c4a2a22015-08-14 14:08:59 +00003499 m_isStrictRawResourceValidationPolicyDisabledForTesting = false;
antti@apple.com1229ead2015-03-30 21:09:14 +00003500}
3501
beidson@apple.com87dc6312015-06-02 18:43:13 +00003502void FrameLoader::applyShouldOpenExternalURLsPolicyToNewDocumentLoader(DocumentLoader& documentLoader, ShouldOpenExternalURLsPolicy propagatedPolicy)
3503{
mitz@apple.comc99c7152015-07-17 21:16:09 +00003504 documentLoader.setShouldOpenExternalURLsPolicy(shouldOpenExternalURLsPolicyToApply(m_frame, propagatedPolicy));
beidson@apple.com87dc6312015-06-02 18:43:13 +00003505}
3506
darin@apple.com90a0f152009-02-01 00:55:03 +00003507bool FrameLoaderClient::hasHTMLView() const
3508{
3509 return true;
3510}
3511
cdumez@apple.com468ca182015-05-15 05:07:22 +00003512RefPtr<Frame> createWindow(Frame& openerFrame, Frame& lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, bool& created)
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003513{
3514 ASSERT(!features.dialog || request.frameName().isEmpty());
3515
darin@apple.com14800c12014-04-27 04:09:45 +00003516 created = false;
3517
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003518 if (!request.frameName().isEmpty() && request.frameName() != "_blank") {
cdumez@apple.com468ca182015-05-15 05:07:22 +00003519 if (RefPtr<Frame> frame = lookupFrame.loader().findFrameForNavigation(request.frameName(), openerFrame.document())) {
jochen@chromium.orgb2c684a2013-05-11 19:09:01 +00003520 if (request.frameName() != "_self") {
3521 if (Page* page = frame->page())
akling@apple.combd774812013-05-17 00:03:01 +00003522 page->chrome().focus();
jochen@chromium.orgb2c684a2013-05-11 19:09:01 +00003523 }
cdumez@apple.com468ca182015-05-15 05:07:22 +00003524 return WTF::move(frame);
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003525 }
3526 }
3527
3528 // Sandboxed frames cannot open new auxiliary browsing contexts.
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +00003529 if (isDocumentSandboxed(openerFrame, SandboxPopups)) {
3530 // 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 +00003531 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 +00003532 return nullptr;
mkwst@chromium.orgb10ebb432012-12-04 18:34:27 +00003533 }
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003534
3535 // FIXME: Setting the referrer should be the caller's responsibility.
3536 FrameLoadRequest requestWithReferrer = request;
cdumez@apple.comd6738dc2015-05-04 23:58:32 +00003537 String referrer = SecurityPolicy::generateReferrerHeader(openerFrame.document()->referrerPolicy(), request.resourceRequest().url(), openerFrame.loader().outgoingReferrer());
jochen@chromium.orgc881e402013-02-28 21:45:58 +00003538 if (!referrer.isEmpty())
3539 requestWithReferrer.resourceRequest().setHTTPReferrer(referrer);
cdumez@apple.comd6738dc2015-05-04 23:58:32 +00003540 FrameLoader::addHTTPOriginIfNeeded(requestWithReferrer.resourceRequest(), openerFrame.loader().outgoingOrigin());
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003541
cdumez@apple.comd6738dc2015-05-04 23:58:32 +00003542 Page* oldPage = openerFrame.page();
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003543 if (!oldPage)
darin@apple.com14800c12014-04-27 04:09:45 +00003544 return nullptr;
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003545
mitz@apple.comc99c7152015-07-17 21:16:09 +00003546 ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicyToApply(openerFrame, request.shouldOpenExternalURLsPolicy());
3547 Page* page = oldPage->chrome().createWindow(&openerFrame, requestWithReferrer, features, NavigationAction(requestWithReferrer.resourceRequest(), shouldOpenExternalURLsPolicy));
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003548 if (!page)
darin@apple.com14800c12014-04-27 04:09:45 +00003549 return nullptr;
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003550
darin@apple.com14800c12014-04-27 04:09:45 +00003551 RefPtr<Frame> frame = &page->mainFrame();
3552
cdumez@apple.comd6738dc2015-05-04 23:58:32 +00003553 frame->loader().forceSandboxFlags(openerFrame.document()->sandboxFlags());
abarth@webkit.org7155e252011-11-04 18:14:58 +00003554
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003555 if (request.frameName() != "_blank")
darin@apple.com14800c12014-04-27 04:09:45 +00003556 frame->tree().setName(request.frameName());
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003557
akling@apple.combd774812013-05-17 00:03:01 +00003558 page->chrome().setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00003559
3560 if (!frame->page())
3561 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00003562 page->chrome().setStatusbarVisible(features.statusBarVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00003563
3564 if (!frame->page())
3565 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00003566 page->chrome().setScrollbarsVisible(features.scrollbarsVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00003567
3568 if (!frame->page())
3569 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00003570 page->chrome().setMenubarVisible(features.menuBarVisible);
darin@apple.com14800c12014-04-27 04:09:45 +00003571
3572 if (!frame->page())
3573 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00003574 page->chrome().setResizable(features.resizable);
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003575
3576 // 'x' and 'y' specify the location of the window, while 'width' and 'height'
kenneth@webkit.orgdc092f72012-11-14 11:05:20 +00003577 // specify the size of the viewport. We can only resize the window, so adjust
3578 // for the difference between the window size and the viewport size.
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003579
darin@apple.com14800c12014-04-27 04:09:45 +00003580 // FIXME: We should reconcile the initialization of viewport arguments between iOS and non-IOS.
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00003581#if !PLATFORM(IOS)
akling@apple.combd774812013-05-17 00:03:01 +00003582 FloatSize viewportSize = page->chrome().pageRect().size();
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00003583 FloatRect windowRect = page->chrome().windowRect();
andersca@apple.comc1242ad2015-08-13 17:37:27 +00003584 if (features.x)
3585 windowRect.setX(*features.x);
3586 if (features.y)
3587 windowRect.setY(*features.y);
ap@apple.com8d15a822013-08-09 23:25:11 +00003588 // Zero width and height mean using default size, not minumum one.
andersca@apple.comc1242ad2015-08-13 17:37:27 +00003589 if (features.width && *features.width)
3590 windowRect.setWidth(*features.width + (windowRect.width() - viewportSize.width()));
3591 if (features.height && *features.height)
3592 windowRect.setHeight(*features.height + (windowRect.height() - viewportSize.height()));
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003593
kenneth@webkit.orgdc092f72012-11-14 11:05:20 +00003594 // Ensure non-NaN values, minimum size as well as being within valid screen area.
3595 FloatRect newWindowRect = DOMWindow::adjustWindowRect(page, windowRect);
3596
darin@apple.com14800c12014-04-27 04:09:45 +00003597 if (!frame->page())
3598 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00003599 page->chrome().setWindowRect(newWindowRect);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00003600#else
3601 // On iOS, width and height refer to the viewport dimensions.
3602 ViewportArguments arguments;
3603 // Zero width and height mean using default size, not minimum one.
andersca@apple.comc1242ad2015-08-13 17:37:27 +00003604 if (features.width && *features.width)
3605 arguments.width = *features.width;
3606 if (features.height && *features.height)
3607 arguments.height = *features.height;
darin@apple.com14800c12014-04-27 04:09:45 +00003608 frame->setViewportArguments(arguments);
dbates@webkit.org46a1c6f2013-12-19 18:10:07 +00003609#endif
3610
darin@apple.com14800c12014-04-27 04:09:45 +00003611 if (!frame->page())
3612 return nullptr;
akling@apple.combd774812013-05-17 00:03:01 +00003613 page->chrome().show();
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003614
3615 created = true;
cdumez@apple.com468ca182015-05-15 05:07:22 +00003616 return WTF::move(frame);
cjerdonek@webkit.orge1d45412010-08-11 17:40:23 +00003617}
3618
ggaren58e230c2006-11-12 04:53:17 +00003619} // namespace WebCore