Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / loader / FrameLoader.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
4  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
5  * Copyright (C) 2008 Alp Toker <alp@atoker.com>
6  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
7  * Copyright (C) 2011 Kris Jordan <krisjordan@gmail.com>
8  * Copyright (C) 2011 Google Inc. All rights reserved.
9  *
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
15  *     notice, this list of conditions and the following disclaimer.
16  * 2.  Redistributions in binary form must reproduce the above copyright
17  *     notice, this list of conditions and the following disclaimer in the
18  *     documentation and/or other materials provided with the distribution.
19  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
20  *     its contributors may be used to endorse or promote products derived
21  *     from this software without specific prior written permission.
22  *
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
35 #include "config.h"
36 #include "core/loader/FrameLoader.h"
37
38 #include "bindings/core/v8/DOMWrapperWorld.h"
39 #include "bindings/core/v8/ScriptController.h"
40 #include "bindings/core/v8/SerializedScriptValue.h"
41 #include "core/HTMLNames.h"
42 #include "core/dom/Document.h"
43 #include "core/dom/Element.h"
44 #include "core/dom/ViewportDescription.h"
45 #include "core/editing/Editor.h"
46 #include "core/editing/UndoStack.h"
47 #include "core/events/PageTransitionEvent.h"
48 #include "core/fetch/FetchContext.h"
49 #include "core/fetch/ResourceFetcher.h"
50 #include "core/fetch/ResourceLoader.h"
51 #include "core/frame/LocalDOMWindow.h"
52 #include "core/frame/FrameHost.h"
53 #include "core/frame/FrameView.h"
54 #include "core/frame/LocalFrame.h"
55 #include "core/frame/PinchViewport.h"
56 #include "core/frame/csp/ContentSecurityPolicy.h"
57 #include "core/html/HTMLFormElement.h"
58 #include "core/html/HTMLFrameOwnerElement.h"
59 #include "core/html/parser/HTMLParserIdioms.h"
60 #include "core/inspector/ConsoleMessage.h"
61 #include "core/inspector/InspectorController.h"
62 #include "core/inspector/InspectorInstrumentation.h"
63 #include "core/loader/DocumentLoadTiming.h"
64 #include "core/loader/DocumentLoader.h"
65 #include "core/loader/FormState.h"
66 #include "core/loader/FormSubmission.h"
67 #include "core/loader/FrameFetchContext.h"
68 #include "core/loader/FrameLoadRequest.h"
69 #include "core/loader/FrameLoaderClient.h"
70 #include "core/loader/ProgressTracker.h"
71 #include "core/loader/UniqueIdentifier.h"
72 #include "core/loader/appcache/ApplicationCacheHost.h"
73 #include "core/page/BackForwardClient.h"
74 #include "core/page/Chrome.h"
75 #include "core/page/ChromeClient.h"
76 #include "core/page/CreateWindow.h"
77 #include "core/page/EventHandler.h"
78 #include "core/page/FrameTree.h"
79 #include "core/page/Page.h"
80 #include "core/frame/Settings.h"
81 #include "core/page/WindowFeatures.h"
82 #include "core/page/scrolling/ScrollingCoordinator.h"
83 #include "core/xml/parser/XMLDocumentParser.h"
84 #include "platform/Logging.h"
85 #include "platform/UserGestureIndicator.h"
86 #include "platform/geometry/FloatRect.h"
87 #include "platform/network/ContentSecurityPolicyResponseHeaders.h"
88 #include "platform/network/HTTPParsers.h"
89 #include "platform/network/ResourceRequest.h"
90 #include "platform/scroll/ScrollAnimator.h"
91 #include "platform/weborigin/SecurityOrigin.h"
92 #include "platform/weborigin/SecurityPolicy.h"
93 #include "public/platform/WebURLRequest.h"
94 #include "wtf/TemporaryChange.h"
95 #include "wtf/text/CString.h"
96 #include "wtf/text/WTFString.h"
97
98 using blink::WebURLRequest;
99
100 namespace blink {
101
102 using namespace HTMLNames;
103
104 bool isBackForwardLoadType(FrameLoadType type)
105 {
106     return type == FrameLoadTypeBackForward;
107 }
108
109 static bool needsHistoryItemRestore(FrameLoadType type)
110 {
111     return type == FrameLoadTypeBackForward || type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin;
112 }
113
114 FrameLoader::FrameLoader(LocalFrame* frame)
115     : m_frame(frame)
116     , m_mixedContentChecker(frame)
117     , m_progressTracker(ProgressTracker::create(frame))
118     , m_state(FrameStateProvisional)
119     , m_loadType(FrameLoadTypeStandard)
120     , m_fetchContext(FrameFetchContext::create(frame))
121     , m_inStopAllLoaders(false)
122     , m_isComplete(false)
123     , m_checkTimer(this, &FrameLoader::checkTimerFired)
124     , m_didAccessInitialDocument(false)
125     , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired)
126     , m_forcedSandboxFlags(SandboxNone)
127     , m_willDetachClient(false)
128 {
129 }
130
131 FrameLoader::~FrameLoader()
132 {
133 }
134
135 void FrameLoader::init()
136 {
137     ResourceRequest initialRequest(KURL(ParsedURLString, emptyString()));
138     initialRequest.setRequestContext(WebURLRequest::RequestContextInternal);
139     initialRequest.setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
140     m_provisionalDocumentLoader = client()->createDocumentLoader(m_frame, initialRequest, SubstituteData());
141     m_provisionalDocumentLoader->startLoadingMainResource();
142     m_frame->document()->cancelParsing();
143     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
144 }
145
146 FrameLoaderClient* FrameLoader::client() const
147 {
148     return static_cast<FrameLoaderClient*>(m_frame->client());
149 }
150
151 void FrameLoader::setDefersLoading(bool defers)
152 {
153     if (m_documentLoader)
154         m_documentLoader->setDefersLoading(defers);
155     if (m_provisionalDocumentLoader)
156         m_provisionalDocumentLoader->setDefersLoading(defers);
157     if (m_policyDocumentLoader)
158         m_policyDocumentLoader->setDefersLoading(defers);
159
160     if (!defers) {
161         if (m_deferredHistoryLoad.isValid()) {
162             loadHistoryItem(m_deferredHistoryLoad.m_item.get(), m_deferredHistoryLoad.m_type, m_deferredHistoryLoad.m_cachePolicy);
163             m_deferredHistoryLoad = DeferredHistoryLoad();
164         }
165         m_frame->navigationScheduler().startTimer();
166         scheduleCheckCompleted();
167     }
168 }
169
170 void FrameLoader::stopLoading()
171 {
172     m_isComplete = true; // to avoid calling completed() in finishedParsing()
173
174     if (m_frame->document() && m_frame->document()->parsing()) {
175         finishedParsing();
176         m_frame->document()->setParsing(false);
177     }
178
179     if (Document* doc = m_frame->document()) {
180         // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior.
181         // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537
182         doc->setReadyState(Document::Complete);
183     }
184
185     // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
186     m_frame->navigationScheduler().cancel();
187 }
188
189 void FrameLoader::saveScrollState()
190 {
191     if (!m_currentItem || !m_frame->view())
192         return;
193
194     // Shouldn't clobber anything if we might still restore later.
195     if (needsHistoryItemRestore(m_loadType) && !m_frame->view()->wasScrolledByUser())
196         return;
197
198     m_currentItem->setScrollPoint(m_frame->view()->scrollPosition());
199
200     if (m_frame->settings()->pinchVirtualViewportEnabled())
201         m_currentItem->setPinchViewportScrollPoint(m_frame->host()->pinchViewport().visibleRect().location());
202     else
203         m_currentItem->setPinchViewportScrollPoint(FloatPoint(-1, -1));
204
205     if (m_frame->isMainFrame())
206         m_currentItem->setPageScaleFactor(m_frame->page()->pageScaleFactor());
207
208     client()->didUpdateCurrentHistoryItem();
209 }
210
211 void FrameLoader::clearScrollPositionAndViewState()
212 {
213     ASSERT(m_frame->isMainFrame());
214     if (!m_currentItem)
215         return;
216     m_currentItem->clearScrollPoint();
217     m_currentItem->setPageScaleFactor(0);
218 }
219
220 bool FrameLoader::closeURL()
221 {
222     saveScrollState();
223
224     // Should only send the pagehide event here if the current document exists.
225     if (m_frame->document())
226         m_frame->document()->dispatchUnloadEvents();
227     stopLoading();
228
229     if (Page* page = m_frame->page())
230         page->undoStack().didUnloadFrame(*m_frame);
231     return true;
232 }
233
234 void FrameLoader::didExplicitOpen()
235 {
236     m_isComplete = false;
237
238     // Calling document.open counts as committing the first real document load.
239     if (!m_stateMachine.committedFirstRealDocumentLoad())
240         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
241
242     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
243     // from a subsequent window.document.open / window.document.write call.
244     // Canceling redirection here works for all cases because document.open
245     // implicitly precedes document.write.
246     m_frame->navigationScheduler().cancel();
247 }
248
249 void FrameLoader::clear()
250 {
251     if (m_stateMachine.creatingInitialEmptyDocument())
252         return;
253
254     m_frame->editor().clear();
255     m_frame->document()->cancelParsing();
256     m_frame->document()->prepareForDestruction();
257     m_frame->document()->removeFocusedElementOfSubtree(m_frame->document());
258
259     m_frame->selection().prepareForDestruction();
260     m_frame->eventHandler().clear();
261     if (m_frame->view())
262         m_frame->view()->clear();
263
264     m_frame->script().enableEval();
265
266     m_frame->navigationScheduler().cancel();
267
268     m_checkTimer.stop();
269
270     if (m_stateMachine.isDisplayingInitialEmptyDocument())
271         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
272 }
273
274 void FrameLoader::setHistoryItemStateForCommit(HistoryCommitType historyCommitType, bool isPushOrReplaceState, PassRefPtr<SerializedScriptValue> stateObject)
275 {
276     if (m_provisionalItem)
277         m_currentItem = m_provisionalItem.release();
278
279     if (!m_currentItem || historyCommitType == StandardCommit) {
280         m_currentItem = HistoryItem::create();
281     } else if (!isPushOrReplaceState && m_documentLoader->url() != m_currentItem->url()) {
282         m_currentItem->generateNewItemSequenceNumber();
283         if (!equalIgnoringFragmentIdentifier(m_documentLoader->url(), m_currentItem->url()))
284             m_currentItem->generateNewDocumentSequenceNumber();
285     }
286
287     m_currentItem->setURL(m_documentLoader->urlForHistory());
288     m_currentItem->setDocumentState(m_frame->document()->formElementsState());
289     m_currentItem->setTarget(m_frame->tree().uniqueName());
290     if (isPushOrReplaceState)
291         m_currentItem->setStateObject(stateObject);
292     m_currentItem->setReferrer(Referrer(m_documentLoader->request().httpReferrer(), m_documentLoader->request().referrerPolicy()));
293     m_currentItem->setFormInfoFromRequest(m_documentLoader->request());
294 }
295
296 static HistoryCommitType loadTypeToCommitType(FrameLoadType type)
297 {
298     switch (type) {
299     case FrameLoadTypeStandard:
300         return StandardCommit;
301     case FrameLoadTypeInitialInChildFrame:
302         return InitialCommitInChildFrame;
303     case FrameLoadTypeBackForward:
304         return BackForwardCommit;
305     default:
306         break;
307     }
308     return HistoryInertCommit;
309 }
310
311 void FrameLoader::receivedFirstData()
312 {
313     if (m_stateMachine.creatingInitialEmptyDocument())
314         return;
315
316     HistoryCommitType historyCommitType = loadTypeToCommitType(m_loadType);
317     if (historyCommitType == StandardCommit && (m_documentLoader->urlForHistory().isEmpty() || (opener() && !m_currentItem && m_documentLoader->originalRequest().url().isEmpty())))
318         historyCommitType = HistoryInertCommit;
319     else if (historyCommitType == InitialCommitInChildFrame && (!m_frame->tree().top()->isLocalFrame() || MixedContentChecker::isMixedContent(toLocalFrame(m_frame->tree().top())->document()->securityOrigin(), m_documentLoader->url())))
320         historyCommitType = HistoryInertCommit;
321     setHistoryItemStateForCommit(historyCommitType);
322
323     if (!m_stateMachine.committedMultipleRealLoads() && m_loadType == FrameLoadTypeStandard)
324         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedMultipleRealLoads);
325
326     client()->dispatchDidCommitLoad(m_frame, m_currentItem.get(), historyCommitType);
327
328     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
329     m_frame->page()->didCommitLoad(m_frame);
330     dispatchDidClearDocumentOfWindowObject();
331 }
332
333 static void didFailContentSecurityPolicyCheck(FrameLoader* loader)
334 {
335     // load event and stopAllLoaders can detach the LocalFrame, so protect it.
336     RefPtr<LocalFrame> frame(loader->frame());
337
338     // Move the page to a unique origin, and cancel the load.
339     frame->document()->enforceSandboxFlags(SandboxOrigin);
340     loader->stopAllLoaders();
341
342     // Fire a load event, as timing attacks would otherwise reveal that the
343     // frame was blocked. This way, it looks like every other cross-origin
344     // page.
345     if (FrameOwner* frameOwner = frame->owner())
346         frameOwner->dispatchLoad();
347 }
348
349 void FrameLoader::didBeginDocument(bool dispatch)
350 {
351     m_isComplete = false;
352     m_frame->document()->setReadyState(Document::Loading);
353
354     if (m_provisionalItem && m_loadType == FrameLoadTypeBackForward)
355         m_frame->domWindow()->statePopped(m_provisionalItem->stateObject());
356
357     if (dispatch)
358         dispatchDidClearDocumentOfWindowObject();
359
360     m_frame->document()->initContentSecurityPolicy(m_documentLoader ? ContentSecurityPolicyResponseHeaders(m_documentLoader->response()) : ContentSecurityPolicyResponseHeaders());
361
362     if (!m_frame->document()->contentSecurityPolicy()->allowAncestors(m_frame)) {
363         didFailContentSecurityPolicyCheck(this);
364         return;
365     }
366
367     Settings* settings = m_frame->document()->settings();
368     if (settings) {
369         m_frame->document()->fetcher()->setImagesEnabled(settings->imagesEnabled());
370         m_frame->document()->fetcher()->setAutoLoadImages(settings->loadsImagesAutomatically());
371     }
372
373     if (m_documentLoader) {
374         const AtomicString& dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
375         if (!dnsPrefetchControl.isEmpty())
376             m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
377
378         String headerContentLanguage = m_documentLoader->response().httpHeaderField("Content-Language");
379         if (!headerContentLanguage.isEmpty()) {
380             size_t commaIndex = headerContentLanguage.find(',');
381             headerContentLanguage.truncate(commaIndex); // kNotFound == -1 == don't truncate
382             headerContentLanguage = headerContentLanguage.stripWhiteSpace(isHTMLSpace<UChar>);
383             if (!headerContentLanguage.isEmpty())
384                 m_frame->document()->setContentLanguage(AtomicString(headerContentLanguage));
385         }
386     }
387
388     if (m_provisionalItem && m_loadType == FrameLoadTypeBackForward)
389         m_frame->document()->setStateForNewFormElements(m_provisionalItem->documentState());
390 }
391
392 void FrameLoader::finishedParsing()
393 {
394     if (m_stateMachine.creatingInitialEmptyDocument())
395         return;
396
397     // This can be called from the LocalFrame's destructor, in which case we shouldn't protect ourselves
398     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
399     // Null-checking the FrameView indicates whether or not we're in the destructor.
400     RefPtr<LocalFrame> protector = m_frame->view() ? m_frame : 0;
401
402     if (client())
403         client()->dispatchDidFinishDocumentLoad();
404
405     checkCompleted();
406
407     if (!m_frame->view())
408         return; // We are being destroyed by something checkCompleted called.
409
410     // Check if the scrollbars are really needed for the content.
411     // If not, remove them, relayout, and repaint.
412     m_frame->view()->restoreScrollbar();
413     scrollToFragmentWithParentBoundary(m_frame->document()->url());
414 }
415
416 void FrameLoader::loadDone()
417 {
418     checkCompleted();
419 }
420
421 bool FrameLoader::allChildrenAreComplete() const
422 {
423     for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
424         if (child->isLocalFrame() && !toLocalFrame(child)->loader().m_isComplete)
425             return false;
426     }
427     return true;
428 }
429
430 bool FrameLoader::allAncestorsAreComplete() const
431 {
432     for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent()) {
433         if (ancestor->isLocalFrame() && !toLocalFrame(ancestor)->document()->loadEventFinished())
434             return false;
435     }
436     return true;
437 }
438
439 void FrameLoader::checkCompleted()
440 {
441     RefPtr<LocalFrame> protect(m_frame);
442
443     if (m_frame->view())
444         m_frame->view()->handleLoadCompleted();
445
446     // Have we completed before?
447     if (m_isComplete)
448         return;
449
450     // Are we still parsing?
451     if (m_frame->document()->parsing())
452         return;
453
454     // Still waiting imports?
455     if (!m_frame->document()->haveImportsLoaded())
456         return;
457
458     // Still waiting for images/scripts?
459     if (m_frame->document()->fetcher()->requestCount())
460         return;
461
462     // Still waiting for elements that don't go through a FrameLoader?
463     if (m_frame->document()->isDelayingLoadEvent())
464         return;
465
466     // Any frame that hasn't completed yet?
467     if (!allChildrenAreComplete())
468         return;
469
470     // OK, completed.
471     m_isComplete = true;
472     m_frame->document()->setReadyState(Document::Complete);
473     if (m_frame->document()->loadEventStillNeeded())
474         m_frame->document()->implicitClose();
475
476     m_frame->navigationScheduler().startTimer();
477
478     completed();
479     if (m_frame->page())
480         checkLoadComplete();
481
482     if (m_frame->view())
483         m_frame->view()->handleLoadCompleted();
484 }
485
486 void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
487 {
488     if (Page* page = m_frame->page()) {
489         if (page->defersLoading())
490             return;
491     }
492     checkCompleted();
493 }
494
495 void FrameLoader::scheduleCheckCompleted()
496 {
497     if (!m_checkTimer.isActive())
498         m_checkTimer.startOneShot(0, FROM_HERE);
499 }
500
501 LocalFrame* FrameLoader::opener()
502 {
503     // FIXME: Temporary hack to stage converting locations that really should be Frame.
504     return client() ? toLocalFrame(client()->opener()) : 0;
505 }
506
507 void FrameLoader::setOpener(LocalFrame* opener)
508 {
509     // If the frame is already detached, the opener has already been cleared.
510     if (client())
511         client()->setOpener(opener);
512 }
513
514 bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason)
515 {
516     Settings* settings = m_frame->settings();
517     bool allowed = client()->allowPlugins(settings && settings->pluginsEnabled());
518     if (!allowed && reason == AboutToInstantiatePlugin)
519         client()->didNotAllowPlugins();
520     return allowed;
521 }
522
523 void FrameLoader::updateForSameDocumentNavigation(const KURL& newURL, SameDocumentNavigationSource sameDocumentNavigationSource, PassRefPtr<SerializedScriptValue> data, FrameLoadType type)
524 {
525     // Update the data source's request with the new URL to fake the URL change
526     m_frame->document()->setURL(newURL);
527     documentLoader()->updateForSameDocumentNavigation(newURL, sameDocumentNavigationSource);
528
529     // Generate start and stop notifications only when loader is completed so that we
530     // don't fire them for fragment redirection that happens in window.onload handler.
531     // See https://bugs.webkit.org/show_bug.cgi?id=31838
532     if (m_frame->document()->loadEventFinished())
533         client()->didStartLoading(NavigationWithinSameDocument);
534
535     HistoryCommitType historyCommitType = loadTypeToCommitType(type);
536     if (!m_currentItem)
537         historyCommitType = HistoryInertCommit;
538
539     setHistoryItemStateForCommit(historyCommitType, sameDocumentNavigationSource == SameDocumentNavigationHistoryApi, data);
540     client()->dispatchDidNavigateWithinPage(m_currentItem.get(), historyCommitType);
541     client()->dispatchDidReceiveTitle(m_frame->document()->title());
542     if (m_frame->document()->loadEventFinished())
543         client()->didStopLoading();
544 }
545
546 void FrameLoader::loadInSameDocument(const KURL& url, PassRefPtr<SerializedScriptValue> stateObject, FrameLoadType type, ClientRedirectPolicy clientRedirect)
547 {
548     // If we have a state object, we cannot also be a new navigation.
549     ASSERT(!stateObject || type == FrameLoadTypeBackForward);
550
551     // If we have a provisional request for a different document, a fragment scroll should cancel it.
552     if (m_provisionalDocumentLoader) {
553         m_provisionalDocumentLoader->stopLoading();
554         if (m_provisionalDocumentLoader)
555             m_provisionalDocumentLoader->detachFromFrame();
556         m_provisionalDocumentLoader = nullptr;
557         if (!m_frame->host())
558             return;
559     }
560     m_loadType = type;
561     saveScrollState();
562
563     KURL oldURL = m_frame->document()->url();
564     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
565     bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier();
566     if (hashChange) {
567         m_frame->eventHandler().stopAutoscroll();
568         m_frame->domWindow()->enqueueHashchangeEvent(oldURL, url);
569     }
570     m_documentLoader->setIsClientRedirect(clientRedirect == ClientRedirect);
571     m_documentLoader->setReplacesCurrentHistoryItem(m_loadType == FrameLoadTypeStandard);
572     updateForSameDocumentNavigation(url, SameDocumentNavigationDefault, nullptr, type);
573
574     m_frame->view()->setWasScrolledByUser(false);
575
576     // It's important to model this as a load that starts and immediately finishes.
577     // Otherwise, the parent frame may think we never finished loading.
578     started();
579
580     // We need to scroll to the fragment whether or not a hash change occurred, since
581     // the user might have scrolled since the previous navigation.
582     scrollToFragmentWithParentBoundary(url);
583
584     m_isComplete = false;
585     checkCompleted();
586
587     m_frame->domWindow()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue());
588 }
589
590 void FrameLoader::completed()
591 {
592     RefPtr<LocalFrame> protect(m_frame);
593
594     for (Frame* descendant = m_frame->tree().traverseNext(m_frame); descendant; descendant = descendant->tree().traverseNext(m_frame)) {
595         if (descendant->isLocalFrame())
596             toLocalFrame(descendant)->navigationScheduler().startTimer();
597     }
598
599     Frame* parent = m_frame->tree().parent();
600     if (parent && parent->isLocalFrame())
601         toLocalFrame(parent)->loader().checkCompleted();
602
603     if (m_frame->view())
604         m_frame->view()->maintainScrollPositionAtAnchor(0);
605 }
606
607 void FrameLoader::started()
608 {
609     for (Frame* frame = m_frame; frame; frame = frame->tree().parent()) {
610         if (frame->isLocalFrame())
611             toLocalFrame(frame)->loader().m_isComplete = false;
612     }
613 }
614
615 void FrameLoader::setReferrerForFrameRequest(ResourceRequest& request, ShouldSendReferrer shouldSendReferrer, Document* originDocument)
616 {
617     if (shouldSendReferrer == NeverSendReferrer) {
618         request.clearHTTPReferrer();
619         return;
620     }
621
622     // Always use the initiating document to generate the referrer.
623     // We need to generateReferrerHeader(), because we might not have enforced ReferrerPolicy or https->http
624     // referrer suppression yet.
625     String argsReferrer(request.httpReferrer());
626     if (argsReferrer.isEmpty())
627         argsReferrer = originDocument->outgoingReferrer();
628     String referrer = SecurityPolicy::generateReferrerHeader(originDocument->referrerPolicy(), request.url(), argsReferrer);
629
630     request.setHTTPReferrer(Referrer(referrer, originDocument->referrerPolicy()));
631     RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
632     request.addHTTPOriginIfNeeded(referrerOrigin->toAtomicString());
633 }
634
635 bool FrameLoader::isScriptTriggeredFormSubmissionInChildFrame(const FrameLoadRequest& request) const
636 {
637     // If this is a child frame and the form submission was triggered by a script, lock the back/forward list
638     // to match IE and Opera.
639     // See https://bugs.webkit.org/show_bug.cgi?id=32383 for the original motivation for this.
640     if (!m_frame->tree().parent() || UserGestureIndicator::processingUserGesture())
641         return false;
642     return request.formState() && request.formState()->formSubmissionTrigger() == SubmittedByJavaScript;
643 }
644
645 FrameLoadType FrameLoader::determineFrameLoadType(const FrameLoadRequest& request)
646 {
647     if (m_frame->tree().parent() && !m_stateMachine.committedFirstRealDocumentLoad())
648         return FrameLoadTypeInitialInChildFrame;
649     if (!m_frame->tree().parent() && !m_frame->page()->backForward().backForwardListCount())
650         return FrameLoadTypeStandard;
651     if (m_provisionalDocumentLoader && request.substituteData().failingURL() == m_provisionalDocumentLoader->url() && m_loadType == FrameLoadTypeBackForward)
652         return FrameLoadTypeBackForward;
653     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
654         return FrameLoadTypeReload;
655     if (request.resourceRequest().cachePolicy() == ReloadBypassingCache)
656         return FrameLoadTypeReloadFromOrigin;
657     if (request.lockBackForwardList() || isScriptTriggeredFormSubmissionInChildFrame(request))
658         return FrameLoadTypeRedirectWithLockedBackForwardList;
659     if (!request.originDocument() && request.resourceRequest().url() == m_documentLoader->urlForHistory())
660         return FrameLoadTypeSame;
661     if (request.substituteData().failingURL() == m_documentLoader->urlForHistory() && m_loadType == FrameLoadTypeReload)
662         return FrameLoadTypeReload;
663     return FrameLoadTypeStandard;
664 }
665
666 bool FrameLoader::prepareRequestForThisFrame(FrameLoadRequest& request)
667 {
668     request.resourceRequest().setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
669
670     // If no origin Document* was specified, skip remaining security checks and assume the caller has fully initialized the FrameLoadRequest.
671     if (!request.originDocument())
672         return true;
673
674     KURL url = request.resourceRequest().url();
675     if (m_frame->script().executeScriptIfJavaScriptURL(url))
676         return false;
677
678     if (!request.originDocument()->securityOrigin()->canDisplay(url)) {
679         reportLocalLoadFailed(m_frame, url.elidedString());
680         return false;
681     }
682
683     if (!request.formState() && request.frameName().isEmpty())
684         request.setFrameName(m_frame->document()->baseTarget());
685
686     setReferrerForFrameRequest(request.resourceRequest(), request.shouldSendReferrer(), request.originDocument());
687     return true;
688 }
689
690 static bool shouldOpenInNewWindow(LocalFrame* targetFrame, const FrameLoadRequest& request, const NavigationAction& action)
691 {
692     if (!targetFrame && !request.frameName().isEmpty())
693         return true;
694     // FIXME: This case is a workaround for the fact that ctrl+clicking a form submission incorrectly
695     // sends as a GET rather than a POST if it creates a new window in a different process.
696     return request.formState() && action.shouldOpenInNewWindow();
697 }
698
699 static WebURLRequest::RequestContext determineRequestContextFromNavigationType(const NavigationType navigationType)
700 {
701     switch (navigationType) {
702     case NavigationTypeLinkClicked:
703         return WebURLRequest::RequestContextHyperlink;
704
705     case NavigationTypeOther:
706         return WebURLRequest::RequestContextLocation;
707
708     case NavigationTypeFormResubmitted:
709     case NavigationTypeFormSubmitted:
710         return WebURLRequest::RequestContextForm;
711
712     case NavigationTypeBackForward:
713     case NavigationTypeReload:
714         return WebURLRequest::RequestContextInternal;
715     }
716     ASSERT_NOT_REACHED();
717     return WebURLRequest::RequestContextHyperlink;
718 }
719
720 void FrameLoader::load(const FrameLoadRequest& passedRequest)
721 {
722     ASSERT(m_frame->document());
723
724     RefPtr<LocalFrame> protect(m_frame);
725
726     if (m_inStopAllLoaders)
727         return;
728
729     FrameLoadRequest request(passedRequest);
730     if (!prepareRequestForThisFrame(request))
731         return;
732
733     RefPtr<LocalFrame> targetFrame = request.formState() ? 0 : findFrameForNavigation(AtomicString(request.frameName()), request.formState() ? request.formState()->sourceDocument() : m_frame->document());
734     if (targetFrame && targetFrame != m_frame) {
735         request.setFrameName("_self");
736         targetFrame->loader().load(request);
737         if (Page* page = targetFrame->page())
738             page->chrome().focus();
739         return;
740     }
741
742     FrameLoadType newLoadType = determineFrameLoadType(request);
743     NavigationAction action(request.resourceRequest(), newLoadType, request.formState(), request.triggeringEvent());
744     if (action.resourceRequest().requestContext() == WebURLRequest::RequestContextUnspecified)
745         action.mutableResourceRequest().setRequestContext(determineRequestContextFromNavigationType(action.type()));
746     if (shouldOpenInNewWindow(targetFrame.get(), request, action)) {
747         if (action.policy() == NavigationPolicyDownload)
748             client()->loadURLExternally(action.resourceRequest(), NavigationPolicyDownload);
749         else
750             createWindowForRequest(request, *m_frame, action.policy(), request.shouldSendReferrer());
751         return;
752     }
753
754     const KURL& url = request.resourceRequest().url();
755     if (!action.shouldOpenInNewWindow() && shouldPerformFragmentNavigation(request.formState(), request.resourceRequest().httpMethod(), newLoadType, url)) {
756         m_documentLoader->setTriggeringAction(action);
757         if (shouldTreatURLAsSameAsCurrent(url))
758             newLoadType = FrameLoadTypeRedirectWithLockedBackForwardList;
759         loadInSameDocument(url, nullptr, newLoadType, request.clientRedirect());
760         return;
761     }
762     bool sameURL = url == m_documentLoader->urlForHistory();
763     loadWithNavigationAction(action, newLoadType, request.formState(), request.substituteData(), request.shouldCheckMainWorldContentSecurityPolicy(), request.clientRedirect());
764     // Example of this case are sites that reload the same URL with a different cookie
765     // driving the generated content, or a master frame with links that drive a target
766     // frame, where the user has clicked on the same link repeatedly.
767     if (sameURL && newLoadType != FrameLoadTypeReload && newLoadType != FrameLoadTypeReloadFromOrigin && request.resourceRequest().httpMethod() != "POST")
768         m_loadType = FrameLoadTypeSame;
769 }
770
771 SubstituteData FrameLoader::defaultSubstituteDataForURL(const KURL& url)
772 {
773     if (!shouldTreatURLAsSrcdocDocument(url))
774         return SubstituteData();
775     String srcdoc = m_frame->deprecatedLocalOwner()->fastGetAttribute(srcdocAttr);
776     ASSERT(!srcdoc.isNull());
777     CString encodedSrcdoc = srcdoc.utf8();
778     return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), "text/html", "UTF-8", KURL());
779 }
780
781 void FrameLoader::reportLocalLoadFailed(LocalFrame* frame, const String& url)
782 {
783     ASSERT(!url.isEmpty());
784     if (!frame)
785         return;
786
787     frame->document()->addConsoleMessage(ConsoleMessage::create(SecurityMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url));
788 }
789
790 // static
791 ResourceRequest FrameLoader::requestFromHistoryItem(HistoryItem* item, ResourceRequestCachePolicy cachePolicy)
792 {
793     RefPtr<FormData> formData = item->formData();
794     ResourceRequest request(item->url(), item->referrer());
795     request.setCachePolicy(cachePolicy);
796     if (formData) {
797         request.setHTTPMethod("POST");
798         request.setHTTPBody(formData);
799         request.setHTTPContentType(item->formContentType());
800         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer().referrer);
801         request.addHTTPOriginIfNeeded(securityOrigin->toAtomicString());
802     }
803     return request;
804 }
805
806 void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const AtomicString& overrideEncoding, ClientRedirectPolicy clientRedirectPolicy)
807 {
808     if (!m_currentItem)
809         return;
810
811     ResourceRequestCachePolicy cachePolicy = reloadPolicy == EndToEndReload ? ReloadBypassingCache : ReloadIgnoringCacheData;
812     ResourceRequest request = requestFromHistoryItem(m_currentItem.get(), cachePolicy);
813     request.setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
814     request.setRequestContext(WebURLRequest::RequestContextInternal);
815
816     // ClientRedirectPolicy is an indication that this load was triggered by
817     // some direct interaction with the page. If this reload is not a client
818     // redirect, we should reuse the referrer from the original load of the
819     // current document. If this reload is a client redirect (e.g., location.reload()),
820     // it was initiated by something in the current document and should
821     // therefore show the current document's url as the referrer.
822     if (clientRedirectPolicy == ClientRedirect)
823         request.setHTTPReferrer(Referrer(m_frame->document()->outgoingReferrer(), m_frame->document()->referrerPolicy()));
824
825     if (!overrideURL.isEmpty()) {
826         request.setURL(overrideURL);
827         request.clearHTTPReferrer();
828     }
829
830     FrameLoadType type = reloadPolicy == EndToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload;
831     loadWithNavigationAction(NavigationAction(request, type), type, nullptr, SubstituteData(), CheckContentSecurityPolicy, clientRedirectPolicy, overrideEncoding);
832 }
833
834 void FrameLoader::stopAllLoaders()
835 {
836     if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal)
837         return;
838
839     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
840     if (m_inStopAllLoaders)
841         return;
842
843     // Calling stopLoading() on the provisional document loader can blow away
844     // the frame from underneath.
845     RefPtr<LocalFrame> protect(m_frame);
846
847     m_inStopAllLoaders = true;
848
849     for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
850         if (child->isLocalFrame())
851             toLocalFrame(child.get())->loader().stopAllLoaders();
852     }
853     if (m_provisionalDocumentLoader)
854         m_provisionalDocumentLoader->stopLoading();
855     if (m_documentLoader)
856         m_documentLoader->stopLoading();
857
858     if (m_provisionalDocumentLoader)
859         m_provisionalDocumentLoader->detachFromFrame();
860     m_provisionalDocumentLoader = nullptr;
861
862     m_checkTimer.stop();
863
864     m_inStopAllLoaders = false;
865
866     // detachFromParent() can be called multiple times on same LocalFrame, which
867     // means we may no longer have a FrameLoaderClient to talk to.
868     if (client())
869         client()->didStopAllLoaders();
870 }
871
872 void FrameLoader::didAccessInitialDocument()
873 {
874     // We only need to notify the client once, and only for the main frame.
875     if (isLoadingMainFrame() && !m_didAccessInitialDocument) {
876         m_didAccessInitialDocument = true;
877         // Notify asynchronously, since this is called within a JavaScript security check.
878         m_didAccessInitialDocumentTimer.startOneShot(0, FROM_HERE);
879     }
880 }
881
882 void FrameLoader::didAccessInitialDocumentTimerFired(Timer<FrameLoader>*)
883 {
884     client()->didAccessInitialDocument();
885 }
886
887 void FrameLoader::notifyIfInitialDocumentAccessed()
888 {
889     if (m_didAccessInitialDocumentTimer.isActive()) {
890         m_didAccessInitialDocumentTimer.stop();
891         didAccessInitialDocumentTimerFired(0);
892     }
893 }
894
895 bool FrameLoader::isLoading() const
896 {
897     if (m_provisionalDocumentLoader)
898         return true;
899     return m_documentLoader && m_documentLoader->isLoading();
900 }
901
902 void FrameLoader::commitProvisionalLoad()
903 {
904     ASSERT(client()->hasWebView());
905     ASSERT(m_state == FrameStateProvisional);
906     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
907     RefPtr<LocalFrame> protect(m_frame);
908
909     // Check if the destination page is allowed to access the previous page's timing information.
910     if (m_frame->document()) {
911         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(pdl->request().url());
912         pdl->timing()->setHasSameOriginAsPreviousDocument(securityOrigin->canRequest(m_frame->document()->url()));
913     }
914
915     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
916     // JavaScript. If the script initiates a new load, we need to abandon the current load,
917     // or the two will stomp each other.
918     // detachChildren will similarly trigger child frame unload event handlers.
919     if (m_documentLoader) {
920         client()->dispatchWillClose();
921         closeURL();
922     }
923     m_frame->detachChildren();
924     if (pdl != m_provisionalDocumentLoader)
925         return;
926     if (m_documentLoader)
927         m_documentLoader->detachFromFrame();
928     m_documentLoader = m_provisionalDocumentLoader.release();
929     m_state = FrameStateCommittedPage;
930
931     if (isLoadingMainFrame())
932         m_frame->page()->chrome().client().needTouchEvents(false);
933
934     client()->transitionToCommittedForNewPage();
935     m_frame->navigationScheduler().cancel();
936     m_frame->editor().clearLastEditCommand();
937
938     // If we are still in the process of initializing an empty document then
939     // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
940     // since it may cause clients to attempt to render the frame.
941     if (!m_stateMachine.creatingInitialEmptyDocument()) {
942         LocalDOMWindow* window = m_frame->domWindow();
943         window->setStatus(String());
944         window->setDefaultStatus(String());
945     }
946     started();
947 }
948
949 bool FrameLoader::isLoadingMainFrame() const
950 {
951     return m_frame->isMainFrame();
952 }
953
954 FrameLoadType FrameLoader::loadType() const
955 {
956     return m_loadType;
957 }
958
959 // This function is an incomprehensible mess and is only used in checkLoadCompleteForThisFrame.
960 // If you're thinking of using it elsewhere, stop right now and reconsider your life.
961 static bool isDocumentDoneLoading(Document* document)
962 {
963     if (!document->loader())
964         return true;
965     if (document->loader()->isLoadingMainResource())
966         return false;
967     if (!document->loadEventFinished()) {
968         if (document->loader()->isLoading() || document->isDelayingLoadEvent())
969             return false;
970     }
971     if (document->fetcher()->requestCount())
972         return false;
973     if (document->processingLoadEvent())
974         return false;
975     if (document->hasActiveParser())
976         return false;
977     return true;
978 }
979
980 bool FrameLoader::checkLoadCompleteForThisFrame()
981 {
982     ASSERT(client()->hasWebView());
983     RefPtr<LocalFrame> protect(m_frame);
984
985     bool allChildrenAreDoneLoading = true;
986     for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
987         if (child->isLocalFrame())
988             allChildrenAreDoneLoading &= toLocalFrame(child.get())->loader().checkLoadCompleteForThisFrame();
989     }
990
991     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
992         const ResourceError& error = m_provisionalDocumentLoader->mainDocumentError();
993         if (error.isNull())
994             return false;
995         RefPtr<DocumentLoader> loader = m_provisionalDocumentLoader;
996         client()->dispatchDidFailProvisionalLoad(error);
997         if (loader != m_provisionalDocumentLoader)
998             return false;
999         m_provisionalDocumentLoader->detachFromFrame();
1000         m_provisionalDocumentLoader = nullptr;
1001         m_progressTracker->progressCompleted();
1002         m_state = FrameStateComplete;
1003         return true;
1004     }
1005
1006     if (!allChildrenAreDoneLoading)
1007         return false;
1008
1009     if (m_state == FrameStateComplete)
1010         return true;
1011     if (m_provisionalDocumentLoader || !m_documentLoader)
1012         return false;
1013     if (!isDocumentDoneLoading(m_frame->document()) && !m_inStopAllLoaders)
1014         return false;
1015
1016     m_state = FrameStateComplete;
1017
1018     // FIXME: Is this subsequent work important if we already navigated away?
1019     // Maybe there are bugs because of that, or extra work we can skip because
1020     // the new page is ready.
1021
1022     // Retry restoring scroll offset since FrameStateComplete disables content
1023     // size clamping.
1024     restoreScrollPositionAndViewState();
1025
1026     if (!m_stateMachine.committedFirstRealDocumentLoad())
1027         return true;
1028
1029     m_progressTracker->progressCompleted();
1030     m_frame->domWindow()->finishedLoading();
1031
1032     const ResourceError& error = m_documentLoader->mainDocumentError();
1033     if (!error.isNull()) {
1034         client()->dispatchDidFailLoad(error);
1035     } else {
1036         // Report mobile vs. desktop page statistics. This will only report on Android.
1037         if (m_frame->isMainFrame())
1038             m_frame->document()->viewportDescription().reportMobilePageStats(m_frame);
1039
1040         client()->dispatchDidFinishLoad();
1041     }
1042     m_loadType = FrameLoadTypeStandard;
1043     return true;
1044 }
1045
1046 void FrameLoader::restoreScrollPositionAndViewState()
1047 {
1048     FrameView* view = m_frame->view();
1049     if (!m_frame->page() || !view || !m_currentItem || !m_stateMachine.committedFirstRealDocumentLoad())
1050         return;
1051
1052     if (!needsHistoryItemRestore(m_loadType))
1053         return;
1054
1055     // This tries to balance 1. restoring as soon as possible, 2. detecting
1056     // clamping to avoid repeatedly popping the scroll position down as the
1057     // page height increases, 3. ignore clamp detection after load completes
1058     // because that may be because the page will never reach its previous
1059     // height.
1060     float mainFrameScale = m_frame->settings()->pinchVirtualViewportEnabled() ? 1 : m_currentItem->pageScaleFactor();
1061     bool canRestoreWithoutClamping = view->clampOffsetAtScale(m_currentItem->scrollPoint(), mainFrameScale) == m_currentItem->scrollPoint();
1062     bool canRestoreWithoutAnnoyingUser = !view->wasScrolledByUser() && (canRestoreWithoutClamping || m_state == FrameStateComplete);
1063     if (!canRestoreWithoutAnnoyingUser)
1064         return;
1065
1066     if (m_frame->isMainFrame() && m_currentItem->pageScaleFactor()) {
1067         FloatPoint pinchViewportOffset(m_currentItem->pinchViewportScrollPoint());
1068         IntPoint frameScrollOffset(m_currentItem->scrollPoint());
1069
1070         m_frame->page()->setPageScaleFactor(m_currentItem->pageScaleFactor(), frameScrollOffset);
1071
1072         if (m_frame->settings()->pinchVirtualViewportEnabled()) {
1073             // If the pinch viewport's offset is (-1, -1) it means the history item
1074             // is an old version of HistoryItem so distribute the scroll between
1075             // the main frame and the pinch viewport as best as we can.
1076             // FIXME(bokan): This legacy distribution can be removed once the virtual viewport
1077             // pinch path is enabled on all platforms for at least one release.
1078             if (pinchViewportOffset.x() == -1 && pinchViewportOffset.y() == -1)
1079                 pinchViewportOffset = FloatPoint(frameScrollOffset - view->scrollPosition());
1080
1081             m_frame->host()->pinchViewport().setLocation(pinchViewportOffset);
1082         }
1083     } else {
1084         view->setScrollPositionNonProgrammatically(m_currentItem->scrollPoint());
1085     }
1086
1087     if (m_frame->isMainFrame()) {
1088         if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
1089             scrollingCoordinator->frameViewRootLayerDidChange(view);
1090     }
1091 }
1092
1093 // Called every time a resource is completely loaded or an error is received.
1094 void FrameLoader::checkLoadComplete()
1095 {
1096     ASSERT(client()->hasWebView());
1097     if (Page* page = m_frame->page()) {
1098         if (page->mainFrame()->isLocalFrame())
1099             page->deprecatedLocalMainFrame()->loader().checkLoadCompleteForThisFrame();
1100     }
1101 }
1102
1103 String FrameLoader::userAgent(const KURL& url) const
1104 {
1105     String userAgent = client()->userAgent(url);
1106     InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent);
1107     return userAgent;
1108 }
1109
1110 void FrameLoader::detachFromParent()
1111 {
1112     // Temporary explosions. We should never re-enter this code when this condition is true.
1113     RELEASE_ASSERT(!m_willDetachClient);
1114     // The caller must protect a reference to m_frame.
1115     ASSERT(m_frame->refCount() > 1);
1116
1117     InspectorInstrumentation::frameDetachedFromParent(m_frame);
1118
1119     if (m_documentLoader)
1120         m_documentLoader->detachFromFrame();
1121     m_documentLoader = nullptr;
1122
1123     if (!client())
1124         return;
1125
1126     TemporaryChange<bool> willDetachClient(m_willDetachClient, true);
1127
1128     // FIXME: All this code belongs up in Page.
1129     Frame* parent = m_frame->tree().parent();
1130     if (parent && parent->isLocalFrame()) {
1131         m_frame->setView(nullptr);
1132         // FIXME: Shouldn't need to check if page() is null here.
1133         if (m_frame->owner() && m_frame->page())
1134             m_frame->page()->decrementSubframeCount();
1135         m_frame->willDetachFrameHost();
1136         detachClient();
1137         toLocalFrame(parent)->loader().scheduleCheckCompleted();
1138     } else {
1139         m_frame->setView(nullptr);
1140         m_frame->willDetachFrameHost();
1141         detachClient();
1142     }
1143     m_frame->detachFromFrameHost();
1144 }
1145
1146 void FrameLoader::detachClient()
1147 {
1148     ASSERT(client());
1149
1150     // Finish all cleanup work that might require talking to the embedder.
1151     m_progressTracker.clear();
1152     setOpener(0);
1153     // Notify ScriptController that the frame is closing, since its cleanup ends up calling
1154     // back to FrameLoaderClient via WindowProxy.
1155     m_frame->script().clearForClose();
1156
1157     // client() should never be null because that means we somehow re-entered
1158     // the frame detach code... but it is sometimes.
1159     // FIXME: Understand why this is happening so we can document this insanity.
1160     if (client()) {
1161         // After this, we must no longer talk to the client since this clears
1162         // its owning reference back to our owning LocalFrame.
1163         client()->detachedFromParent();
1164         m_frame->clearClient();
1165     }
1166 }
1167
1168 void FrameLoader::receivedMainResourceError(const ResourceError& error)
1169 {
1170     // Retain because the stop may release the last reference to it.
1171     RefPtr<LocalFrame> protect(m_frame);
1172
1173     if (m_frame->document()->parser())
1174         m_frame->document()->parser()->stopParsing();
1175
1176     // FIXME: We really ought to be able to just check for isCancellation() here, but there are some
1177     // ResourceErrors that setIsCancellation() but aren't created by ResourceError::cancelledError().
1178     ResourceError c(ResourceError::cancelledError(KURL()));
1179     if ((error.errorCode() != c.errorCode() || error.domain() != c.domain()) && m_frame->owner()) {
1180         // FIXME: For now, fallback content doesn't work cross process.
1181         ASSERT(m_frame->owner()->isLocal());
1182         m_frame->deprecatedLocalOwner()->renderFallbackContent();
1183     }
1184
1185     checkCompleted();
1186     if (m_frame->page())
1187         checkLoadComplete();
1188 }
1189
1190 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url)
1191 {
1192     ASSERT(loadType != FrameLoadTypeReloadFromOrigin);
1193     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
1194     // currently displaying a frameset, or if the URL does not have a fragment.
1195     return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET"))
1196         && loadType != FrameLoadTypeReload
1197         && loadType != FrameLoadTypeSame
1198         && loadType != FrameLoadTypeBackForward
1199         && url.hasFragmentIdentifier()
1200         && equalIgnoringFragmentIdentifier(m_frame->document()->url(), url)
1201         // We don't want to just scroll if a link from within a
1202         // frameset is trying to reload the frameset into _top.
1203         && !m_frame->document()->isFrameSet();
1204 }
1205
1206 void FrameLoader::scrollToFragmentWithParentBoundary(const KURL& url)
1207 {
1208     FrameView* view = m_frame->view();
1209     if (!view)
1210         return;
1211
1212     // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
1213     RefPtr<LocalFrame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame->document()->findUnsafeParentScrollPropagationBoundary() : 0);
1214
1215     if (boundaryFrame)
1216         boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
1217
1218     view->scrollToFragment(url);
1219
1220     if (boundaryFrame)
1221         boundaryFrame->view()->setSafeToPropagateScrollToParent(true);
1222 }
1223
1224 bool FrameLoader::shouldClose()
1225 {
1226     Page* page = m_frame->page();
1227     if (!page || !page->chrome().canRunBeforeUnloadConfirmPanel())
1228         return true;
1229
1230     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
1231     Vector<RefPtr<LocalFrame> > targetFrames;
1232     targetFrames.append(m_frame);
1233     for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().traverseNext(m_frame)) {
1234         // FIXME: There is not yet any way to dispatch events to out-of-process frames.
1235         if (child->isLocalFrame())
1236             targetFrames.append(toLocalFrame(child));
1237     }
1238
1239     bool shouldClose = false;
1240     {
1241         NavigationDisablerForBeforeUnload navigationDisabler;
1242         size_t i;
1243
1244         bool didAllowNavigation = false;
1245         for (i = 0; i < targetFrames.size(); i++) {
1246             if (!targetFrames[i]->tree().isDescendantOf(m_frame))
1247                 continue;
1248             if (!targetFrames[i]->document()->dispatchBeforeUnloadEvent(page->chrome(), didAllowNavigation))
1249                 break;
1250         }
1251
1252         if (i == targetFrames.size())
1253             shouldClose = true;
1254     }
1255     return shouldClose;
1256 }
1257
1258 bool FrameLoader::validateTransitionNavigationMode()
1259 {
1260     if (frame()->document()->inQuirksMode()) {
1261         frame()->document()->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Ignoring transition elements due to quirks mode."));
1262         return false;
1263     }
1264
1265     // FIXME(oysteine): Also check for width=device-width here, to avoid zoom/scaling issues.
1266     return true;
1267 }
1268
1269 bool FrameLoader::dispatchNavigationTransitionData()
1270 {
1271     Vector<Document::TransitionElementData> elementData;
1272     frame()->document()->getTransitionElementData(elementData);
1273     if (elementData.isEmpty() || !validateTransitionNavigationMode())
1274         return false;
1275
1276     Vector<Document::TransitionElementData>::iterator iter = elementData.begin();
1277     for (; iter != elementData.end(); ++iter)
1278         client()->dispatchAddNavigationTransitionData(iter->scope, iter->selector, iter->markup);
1279
1280     return true;
1281 }
1282
1283 void FrameLoader::loadWithNavigationAction(const NavigationAction& action, FrameLoadType type, PassRefPtrWillBeRawPtr<FormState> formState, const SubstituteData& substituteData, ContentSecurityPolicyCheck shouldCheckMainWorldContentSecurityPolicy, ClientRedirectPolicy clientRedirect, const AtomicString& overrideEncoding)
1284 {
1285     ASSERT(client()->hasWebView());
1286     if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal)
1287         return;
1288
1289     const ResourceRequest& request = action.resourceRequest();
1290
1291     // The current load should replace the history item if it is the first real
1292     // load of the frame.
1293     bool replacesCurrentHistoryItem = false;
1294     if (type == FrameLoadTypeRedirectWithLockedBackForwardList
1295         || !m_stateMachine.committedFirstRealDocumentLoad()) {
1296         replacesCurrentHistoryItem = true;
1297     }
1298
1299     m_policyDocumentLoader = client()->createDocumentLoader(m_frame, request, substituteData.isValid() ? substituteData : defaultSubstituteDataForURL(request.url()));
1300     m_policyDocumentLoader->setTriggeringAction(action);
1301     m_policyDocumentLoader->setReplacesCurrentHistoryItem(replacesCurrentHistoryItem);
1302     m_policyDocumentLoader->setIsClientRedirect(clientRedirect == ClientRedirect);
1303
1304     Frame* parent = m_frame->tree().parent();
1305     if (parent && parent->isLocalFrame())
1306         m_policyDocumentLoader->setOverrideEncoding(toLocalFrame(parent)->loader().documentLoader()->overrideEncoding());
1307     else if (!overrideEncoding.isEmpty())
1308         m_policyDocumentLoader->setOverrideEncoding(overrideEncoding);
1309     else if (m_documentLoader)
1310         m_policyDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
1311
1312
1313     bool isTransitionNavigation = false;
1314     if (RuntimeEnabledFeatures::navigationTransitionsEnabled())
1315         isTransitionNavigation = dispatchNavigationTransitionData();
1316
1317     // stopAllLoaders can detach the LocalFrame, so protect it.
1318     RefPtr<LocalFrame> protect(m_frame);
1319     if ((!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request, shouldCheckMainWorldContentSecurityPolicy, isTransitionNavigation) || !shouldClose()) && m_policyDocumentLoader) {
1320         m_policyDocumentLoader->detachFromFrame();
1321         m_policyDocumentLoader = nullptr;
1322         return;
1323     }
1324
1325     if (m_provisionalDocumentLoader) {
1326         m_provisionalDocumentLoader->stopLoading();
1327         if (m_provisionalDocumentLoader)
1328             m_provisionalDocumentLoader->detachFromFrame();
1329         m_provisionalDocumentLoader = nullptr;
1330     }
1331     m_checkTimer.stop();
1332
1333     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
1334     // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
1335     if (!m_frame->page() || !m_policyDocumentLoader)
1336         return;
1337
1338     if (isLoadingMainFrame())
1339         m_frame->page()->inspectorController().resume();
1340     m_frame->navigationScheduler().cancel();
1341
1342     m_provisionalDocumentLoader = m_policyDocumentLoader.release();
1343     m_loadType = type;
1344     m_state = FrameStateProvisional;
1345
1346     if (formState)
1347         client()->dispatchWillSubmitForm(formState->form());
1348
1349     m_progressTracker->progressStarted();
1350     if (m_provisionalDocumentLoader->isClientRedirect())
1351         m_provisionalDocumentLoader->appendRedirect(m_frame->document()->url());
1352     m_provisionalDocumentLoader->appendRedirect(m_provisionalDocumentLoader->request().url());
1353     client()->dispatchDidStartProvisionalLoad(isTransitionNavigation);
1354     ASSERT(m_provisionalDocumentLoader);
1355     m_provisionalDocumentLoader->startLoadingMainResource();
1356 }
1357
1358 void FrameLoader::applyUserAgent(ResourceRequest& request)
1359 {
1360     String userAgent = this->userAgent(request.url());
1361     ASSERT(!userAgent.isNull());
1362     request.setHTTPUserAgent(AtomicString(userAgent));
1363 }
1364
1365 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url, unsigned long requestIdentifier)
1366 {
1367     UseCounter::count(m_frame->domWindow()->document(), UseCounter::XFrameOptions);
1368
1369     Frame* topFrame = m_frame->tree().top();
1370     if (m_frame == topFrame)
1371         return false;
1372
1373     XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
1374
1375     switch (disposition) {
1376     case XFrameOptionsSameOrigin: {
1377         UseCounter::count(m_frame->domWindow()->document(), UseCounter::XFrameOptionsSameOrigin);
1378         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
1379         // Out-of-process ancestors are always a different origin.
1380         if (!topFrame->isLocalFrame() || !origin->isSameSchemeHostPort(toLocalFrame(topFrame)->document()->securityOrigin()))
1381             return true;
1382         for (Frame* frame = m_frame->tree().parent(); frame; frame = frame->tree().parent()) {
1383             if (!frame->isLocalFrame() || !origin->isSameSchemeHostPort(toLocalFrame(frame)->document()->securityOrigin())) {
1384                 UseCounter::count(m_frame->domWindow()->document(), UseCounter::XFrameOptionsSameOriginWithBadAncestorChain);
1385                 break;
1386             }
1387         }
1388         return false;
1389     }
1390     case XFrameOptionsDeny:
1391         return true;
1392     case XFrameOptionsAllowAll:
1393         return false;
1394     case XFrameOptionsConflict: {
1395         RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.elidedString() + "'. Falling back to 'DENY'.");
1396         consoleMessage->setRequestIdentifier(requestIdentifier);
1397         m_frame->document()->addMessage(consoleMessage.release());
1398         return true;
1399     }
1400     case XFrameOptionsInvalid: {
1401         RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, "Invalid 'X-Frame-Options' header encountered when loading '" + url.elidedString() + "': '" + content + "' is not a recognized directive. The header will be ignored.");
1402         consoleMessage->setRequestIdentifier(requestIdentifier);
1403         m_frame->document()->addMessage(consoleMessage.release());
1404         return false;
1405     }
1406     default:
1407         ASSERT_NOT_REACHED();
1408         return false;
1409     }
1410 }
1411
1412 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
1413 {
1414     return m_currentItem && url == m_currentItem->url();
1415 }
1416
1417 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const KURL& url) const
1418 {
1419     if (!equalIgnoringCase(url.string(), "about:srcdoc"))
1420         return false;
1421     HTMLFrameOwnerElement* ownerElement = m_frame->deprecatedLocalOwner();
1422     if (!isHTMLIFrameElement(ownerElement))
1423         return false;
1424     return ownerElement->fastHasAttribute(srcdocAttr);
1425 }
1426
1427 LocalFrame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
1428 {
1429     ASSERT(activeDocument);
1430     Frame* frame = m_frame->tree().find(name);
1431     if (!frame || !frame->isLocalFrame() || !activeDocument->canNavigate(toLocalFrame(*frame)))
1432         return 0;
1433     return toLocalFrame(frame);
1434 }
1435
1436 void FrameLoader::loadHistoryItem(HistoryItem* item, HistoryLoadType historyLoadType, ResourceRequestCachePolicy cachePolicy)
1437 {
1438     RefPtr<LocalFrame> protect(m_frame);
1439     if (m_frame->page()->defersLoading()) {
1440         m_deferredHistoryLoad = DeferredHistoryLoad(item, historyLoadType, cachePolicy);
1441         return;
1442     }
1443
1444     m_provisionalItem = item;
1445     if (historyLoadType == HistorySameDocumentLoad) {
1446         loadInSameDocument(item->url(), item->stateObject(), FrameLoadTypeBackForward, NotClientRedirect);
1447         restoreScrollPositionAndViewState();
1448         return;
1449     }
1450
1451     ResourceRequest request = requestFromHistoryItem(item, cachePolicy);
1452     request.setFrameType(m_frame->isMainFrame() ? WebURLRequest::FrameTypeTopLevel : WebURLRequest::FrameTypeNested);
1453     request.setRequestContext(WebURLRequest::RequestContextInternal);
1454     loadWithNavigationAction(NavigationAction(request, FrameLoadTypeBackForward), FrameLoadTypeBackForward, nullptr, SubstituteData(), CheckContentSecurityPolicy);
1455 }
1456
1457 void FrameLoader::dispatchDocumentElementAvailable()
1458 {
1459     client()->documentElementAvailable();
1460 }
1461
1462 void FrameLoader::dispatchDidClearDocumentOfWindowObject()
1463 {
1464     if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript))
1465         return;
1466
1467     if (Page* page = m_frame->page())
1468         page->inspectorController().didClearDocumentOfWindowObject(m_frame);
1469     InspectorInstrumentation::didClearDocumentOfWindowObject(m_frame);
1470
1471     // We just cleared the document, not the entire window object, but for the
1472     // embedder that's close enough.
1473     client()->dispatchDidClearWindowObjectInMainWorld();
1474 }
1475
1476 void FrameLoader::dispatchDidClearWindowObjectInMainWorld()
1477 {
1478     if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript))
1479         return;
1480
1481     client()->dispatchDidClearWindowObjectInMainWorld();
1482 }
1483
1484 SandboxFlags FrameLoader::effectiveSandboxFlags() const
1485 {
1486     SandboxFlags flags = m_forcedSandboxFlags;
1487     // FIXME: We need a way to propagate sandbox flags to out-of-process frames.
1488     Frame* parentFrame = m_frame->tree().parent();
1489     if (parentFrame && parentFrame->isLocalFrame())
1490         flags |= toLocalFrame(parentFrame)->document()->sandboxFlags();
1491     if (FrameOwner* frameOwner = m_frame->owner())
1492         flags |= frameOwner->sandboxFlags();
1493     return flags;
1494 }
1495
1496 } // namespace blink