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