Home | History | Annotate | Download | only in loader
      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 (at) atoker.com>
      6  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
      7  * Copyright (C) 2011 Kris Jordan <krisjordan (at) 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 "HTMLNames.h"
     39 #include "bindings/v8/DOMWrapperWorld.h"
     40 #include "bindings/v8/ScriptController.h"
     41 #include "bindings/v8/SerializedScriptValue.h"
     42 #include "core/dom/Document.h"
     43 #include "core/dom/Element.h"
     44 #include "core/editing/Editor.h"
     45 #include "core/editing/UndoStack.h"
     46 #include "core/events/Event.h"
     47 #include "core/events/PageTransitionEvent.h"
     48 #include "core/events/ThreadLocalEventNames.h"
     49 #include "core/fetch/FetchContext.h"
     50 #include "core/fetch/ResourceFetcher.h"
     51 #include "core/fetch/ResourceLoader.h"
     52 #include "core/frame/ContentSecurityPolicy.h"
     53 #include "core/frame/ContentSecurityPolicyResponseHeaders.h"
     54 #include "core/frame/DOMWindow.h"
     55 #include "core/frame/Frame.h"
     56 #include "core/frame/FrameView.h"
     57 #include "core/html/HTMLFormElement.h"
     58 #include "core/html/HTMLFrameOwnerElement.h"
     59 #include "core/html/parser/HTMLParserIdioms.h"
     60 #include "core/inspector/InspectorController.h"
     61 #include "core/inspector/InspectorInstrumentation.h"
     62 #include "core/loader/DocumentLoadTiming.h"
     63 #include "core/loader/DocumentLoader.h"
     64 #include "core/loader/FormState.h"
     65 #include "core/loader/FormSubmission.h"
     66 #include "core/loader/FrameFetchContext.h"
     67 #include "core/loader/FrameLoadRequest.h"
     68 #include "core/loader/FrameLoaderClient.h"
     69 #include "core/loader/ProgressTracker.h"
     70 #include "core/loader/UniqueIdentifier.h"
     71 #include "core/loader/appcache/ApplicationCacheHost.h"
     72 #include "core/page/BackForwardClient.h"
     73 #include "core/page/Chrome.h"
     74 #include "core/page/ChromeClient.h"
     75 #include "core/page/CreateWindow.h"
     76 #include "core/page/EventHandler.h"
     77 #include "core/page/FrameTree.h"
     78 #include "core/page/Page.h"
     79 #include "core/frame/Settings.h"
     80 #include "core/page/WindowFeatures.h"
     81 #include "core/page/scrolling/ScrollingCoordinator.h"
     82 #include "core/xml/parser/XMLDocumentParser.h"
     83 #include "modules/webdatabase/DatabaseManager.h"
     84 #include "platform/Logging.h"
     85 #include "platform/UserGestureIndicator.h"
     86 #include "platform/geometry/FloatRect.h"
     87 #include "platform/network/HTTPParsers.h"
     88 #include "platform/network/ResourceRequest.h"
     89 #include "platform/scroll/ScrollAnimator.h"
     90 #include "platform/weborigin/SecurityOrigin.h"
     91 #include "platform/weborigin/SecurityPolicy.h"
     92 #include "wtf/TemporaryChange.h"
     93 #include "wtf/text/CString.h"
     94 #include "wtf/text/WTFString.h"
     95 
     96 namespace WebCore {
     97 
     98 using namespace HTMLNames;
     99 
    100 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
    101 
    102 bool isBackForwardLoadType(FrameLoadType type)
    103 {
    104     return type == FrameLoadTypeBackForward;
    105 }
    106 
    107 class FrameLoader::FrameProgressTracker {
    108 public:
    109     static PassOwnPtr<FrameProgressTracker> create(Frame* frame) { return adoptPtr(new FrameProgressTracker(frame)); }
    110     ~FrameProgressTracker()
    111     {
    112         ASSERT(!m_inProgress || m_frame->page());
    113         if (m_inProgress)
    114             m_frame->page()->progress().progressCompleted(m_frame);
    115     }
    116 
    117     void progressStarted()
    118     {
    119         ASSERT(m_frame->page());
    120         if (!m_inProgress)
    121             m_frame->page()->progress().progressStarted(m_frame);
    122         m_inProgress = true;
    123     }
    124 
    125     void progressCompleted()
    126     {
    127         ASSERT(m_inProgress);
    128         ASSERT(m_frame->page());
    129         m_inProgress = false;
    130         m_frame->page()->progress().progressCompleted(m_frame);
    131     }
    132 
    133 private:
    134     FrameProgressTracker(Frame* frame)
    135         : m_frame(frame)
    136         , m_inProgress(false)
    137     {
    138     }
    139 
    140     Frame* m_frame;
    141     bool m_inProgress;
    142 };
    143 
    144 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
    145     : m_frame(frame)
    146     , m_client(client)
    147     , m_mixedContentChecker(frame)
    148     , m_state(FrameStateProvisional)
    149     , m_loadType(FrameLoadTypeStandard)
    150     , m_fetchContext(FrameFetchContext::create(frame))
    151     , m_inStopAllLoaders(false)
    152     , m_isComplete(false)
    153     , m_checkTimer(this, &FrameLoader::checkTimerFired)
    154     , m_shouldCallCheckCompleted(false)
    155     , m_opener(0)
    156     , m_didAccessInitialDocument(false)
    157     , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired)
    158     , m_forcedSandboxFlags(SandboxNone)
    159 {
    160 }
    161 
    162 FrameLoader::~FrameLoader()
    163 {
    164     setOpener(0);
    165 
    166     HashSet<Frame*>::iterator end = m_openedFrames.end();
    167     for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it)
    168         (*it)->loader().m_opener = 0;
    169 
    170     m_client->frameLoaderDestroyed();
    171 }
    172 
    173 void FrameLoader::init()
    174 {
    175     // This somewhat odd set of steps gives the frame an initial empty document.
    176     m_provisionalDocumentLoader = m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, emptyString())), SubstituteData());
    177     m_provisionalDocumentLoader->setFrame(m_frame);
    178     m_provisionalDocumentLoader->startLoadingMainResource();
    179     m_frame->document()->cancelParsing();
    180     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
    181     m_progressTracker = FrameProgressTracker::create(m_frame);
    182 }
    183 
    184 void FrameLoader::setDefersLoading(bool defers)
    185 {
    186     if (m_documentLoader)
    187         m_documentLoader->setDefersLoading(defers);
    188     if (m_provisionalDocumentLoader)
    189         m_provisionalDocumentLoader->setDefersLoading(defers);
    190     if (m_policyDocumentLoader)
    191         m_policyDocumentLoader->setDefersLoading(defers);
    192 
    193     if (!defers) {
    194         m_frame->navigationScheduler().startTimer();
    195         startCheckCompleteTimer();
    196     }
    197 }
    198 
    199 void FrameLoader::stopLoading()
    200 {
    201     m_isComplete = true; // to avoid calling completed() in finishedParsing()
    202 
    203     if (m_frame->document() && m_frame->document()->parsing()) {
    204         finishedParsing();
    205         m_frame->document()->setParsing(false);
    206     }
    207 
    208     if (Document* doc = m_frame->document()) {
    209         // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior.
    210         // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537
    211         doc->setReadyState(Document::Complete);
    212 
    213         // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here?
    214         DatabaseManager::manager().stopDatabases(doc, 0);
    215     }
    216 
    217     // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
    218     m_frame->navigationScheduler().cancel();
    219 }
    220 
    221 void FrameLoader::saveDocumentAndScrollState()
    222 {
    223     if (!m_currentItem)
    224         return;
    225 
    226     Document* document = m_frame->document();
    227     if (m_currentItem->isCurrentDocument(document) && document->isActive())
    228         m_currentItem->setDocumentState(document->formElementsState());
    229 
    230     if (!m_frame->view())
    231         return;
    232 
    233     m_currentItem->setScrollPoint(m_frame->view()->scrollPosition());
    234     if (m_frame->isMainFrame() && !m_frame->page()->inspectorController().deviceEmulationEnabled())
    235         m_currentItem->setPageScaleFactor(m_frame->page()->pageScaleFactor());
    236 }
    237 
    238 void FrameLoader::clearScrollPositionAndViewState()
    239 {
    240     ASSERT(m_frame->isMainFrame());
    241     if (!m_currentItem)
    242         return;
    243     m_currentItem->clearScrollPoint();
    244     m_currentItem->setPageScaleFactor(0);
    245 }
    246 
    247 bool FrameLoader::closeURL()
    248 {
    249     // This is done when a back/forward navigation begins (and the current item
    250     // changes) in loadHistoryItem(). Saving now will save the state will save
    251     // to the wrong item if the navigation is back/forward.
    252     if (m_loadType != FrameLoadTypeBackForward)
    253         saveDocumentAndScrollState();
    254 
    255     // Should only send the pagehide event here if the current document exists.
    256     if (m_frame->document())
    257         m_frame->document()->dispatchUnloadEvents();
    258     stopLoading();
    259 
    260     if (Page* page = m_frame->page())
    261         page->undoStack().didUnloadFrame(*m_frame);
    262     return true;
    263 }
    264 
    265 void FrameLoader::didExplicitOpen()
    266 {
    267     m_isComplete = false;
    268 
    269     // Calling document.open counts as committing the first real document load.
    270     if (!m_stateMachine.committedFirstRealDocumentLoad())
    271         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
    272 
    273     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
    274     // from a subsequent window.document.open / window.document.write call.
    275     // Canceling redirection here works for all cases because document.open
    276     // implicitly precedes document.write.
    277     m_frame->navigationScheduler().cancel();
    278 }
    279 
    280 void FrameLoader::clear(ClearOptions options)
    281 {
    282     if (m_stateMachine.creatingInitialEmptyDocument())
    283         return;
    284 
    285     m_frame->editor().clear();
    286     m_frame->document()->cancelParsing();
    287     m_frame->document()->prepareForDestruction();
    288     m_frame->document()->removeFocusedElementOfSubtree(m_frame->document());
    289 
    290     // Do this after detaching the document so that the unload event works.
    291     if (options & ClearWindowProperties) {
    292         InspectorInstrumentation::frameWindowDiscarded(m_frame, m_frame->domWindow());
    293         m_frame->domWindow()->reset();
    294         m_frame->script().clearWindowShell();
    295     }
    296 
    297     m_frame->selection().prepareForDestruction();
    298     m_frame->eventHandler().clear();
    299     if (m_frame->view())
    300         m_frame->view()->clear();
    301 
    302     if (options & ClearWindowObject) {
    303         // Do not drop the DOMWindow (and Document) before the ScriptController and view are cleared
    304         // as some destructors might still try to access the document.
    305         m_frame->setDOMWindow(0);
    306     }
    307 
    308     if (options & ClearScriptObjects)
    309         m_frame->script().clearScriptObjects();
    310 
    311     m_frame->script().enableEval();
    312 
    313     m_frame->navigationScheduler().clear();
    314 
    315     m_checkTimer.stop();
    316     m_shouldCallCheckCompleted = false;
    317 
    318     if (m_stateMachine.isDisplayingInitialEmptyDocument())
    319         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
    320 }
    321 
    322 void FrameLoader::setHistoryItemStateForCommit(HistoryItemPolicy historyItemPolicy)
    323 {
    324     if (!m_currentItem || historyItemPolicy == CreateNewHistoryItem || m_currentItem->url() != m_documentLoader->url()) {
    325         if (!m_currentItem || historyItemPolicy == CreateNewHistoryItem)
    326             m_currentItem = HistoryItem::create();
    327         else
    328             m_currentItem->reset();
    329         const KURL& unreachableURL = m_documentLoader->unreachableURL();
    330         const KURL& url = unreachableURL.isEmpty() ? m_documentLoader->requestURL() : unreachableURL;
    331         const KURL& originalURL = unreachableURL.isEmpty() ? m_documentLoader->originalURL() : unreachableURL;
    332         m_currentItem->setURL(url);
    333         m_currentItem->setTarget(m_frame->tree().uniqueName());
    334         m_currentItem->setTargetFrameID(m_frame->frameID());
    335         m_currentItem->setOriginalURLString(originalURL.string());
    336     }
    337     m_currentItem->setFormInfoFromRequest(m_documentLoader->request());
    338 }
    339 
    340 void FrameLoader::receivedFirstData()
    341 {
    342     if (m_stateMachine.creatingInitialEmptyDocument())
    343         return;
    344     NavigationHistoryPolicy navigationHistoryPolicy = NavigationReusedHistoryEntry;
    345     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isURLValidForNewHistoryEntry())
    346         navigationHistoryPolicy = NavigationCreatedHistoryEntry;
    347     HistoryItemPolicy historyItemPolicy = DoNotCreateNewHistoryItem;
    348     if (m_loadType == FrameLoadTypeInitialInChildFrame || navigationHistoryPolicy == NavigationCreatedHistoryEntry)
    349         historyItemPolicy = CreateNewHistoryItem;
    350     setHistoryItemStateForCommit(historyItemPolicy);
    351 
    352     if (!m_stateMachine.committedMultipleRealLoads() && navigationHistoryPolicy == NavigationCreatedHistoryEntry)
    353         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedMultipleRealLoads);
    354 
    355     m_client->dispatchDidCommitLoad(m_frame, m_currentItem.get(), navigationHistoryPolicy);
    356 
    357     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
    358     m_frame->page()->didCommitLoad(m_frame);
    359     dispatchDidClearWindowObjectsInAllWorlds();
    360 }
    361 
    362 void FrameLoader::didBeginDocument(bool dispatch)
    363 {
    364     m_isComplete = false;
    365     m_frame->document()->setReadyState(Document::Loading);
    366 
    367     if (m_currentItem && m_loadType == FrameLoadTypeBackForward)
    368         m_frame->domWindow()->statePopped(m_currentItem->stateObject());
    369 
    370     if (dispatch)
    371         dispatchDidClearWindowObjectsInAllWorlds();
    372 
    373     m_frame->document()->initContentSecurityPolicy(m_documentLoader ? ContentSecurityPolicyResponseHeaders(m_documentLoader->response()) : ContentSecurityPolicyResponseHeaders());
    374 
    375     Settings* settings = m_frame->document()->settings();
    376     if (settings) {
    377         m_frame->document()->fetcher()->setImagesEnabled(settings->imagesEnabled());
    378         m_frame->document()->fetcher()->setAutoLoadImages(settings->loadsImagesAutomatically());
    379     }
    380 
    381     if (m_documentLoader) {
    382         const AtomicString& dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
    383         if (!dnsPrefetchControl.isEmpty())
    384             m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
    385 
    386         String headerContentLanguage = m_documentLoader->response().httpHeaderField("Content-Language");
    387         if (!headerContentLanguage.isEmpty()) {
    388             size_t commaIndex = headerContentLanguage.find(',');
    389             headerContentLanguage.truncate(commaIndex); // kNotFound == -1 == don't truncate
    390             headerContentLanguage = headerContentLanguage.stripWhiteSpace(isHTMLSpace<UChar>);
    391             if (!headerContentLanguage.isEmpty())
    392                 m_frame->document()->setContentLanguage(AtomicString(headerContentLanguage));
    393         }
    394     }
    395 
    396     if (m_currentItem && m_loadType == FrameLoadTypeBackForward)
    397         m_frame->document()->setStateForNewFormElements(m_currentItem->documentState());
    398 }
    399 
    400 void FrameLoader::finishedParsing()
    401 {
    402     if (m_stateMachine.creatingInitialEmptyDocument())
    403         return;
    404 
    405     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
    406     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
    407     // Null-checking the FrameView indicates whether or not we're in the destructor.
    408     RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
    409 
    410     m_client->dispatchDidFinishDocumentLoad();
    411 
    412     checkCompleted();
    413 
    414     if (!m_frame->view())
    415         return; // We are being destroyed by something checkCompleted called.
    416 
    417     // Check if the scrollbars are really needed for the content.
    418     // If not, remove them, relayout, and repaint.
    419     m_frame->view()->restoreScrollbar();
    420     scrollToFragmentWithParentBoundary(m_frame->document()->url());
    421 }
    422 
    423 void FrameLoader::loadDone()
    424 {
    425     checkCompleted();
    426 }
    427 
    428 bool FrameLoader::allChildrenAreComplete() const
    429 {
    430     for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
    431         if (!child->loader().m_isComplete)
    432             return false;
    433     }
    434     return true;
    435 }
    436 
    437 bool FrameLoader::allAncestorsAreComplete() const
    438 {
    439     for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent()) {
    440         if (!ancestor->document()->loadEventFinished())
    441             return false;
    442     }
    443     return true;
    444 }
    445 
    446 void FrameLoader::checkCompleted()
    447 {
    448     RefPtr<Frame> protect(m_frame);
    449     m_shouldCallCheckCompleted = false;
    450 
    451     if (m_frame->view())
    452         m_frame->view()->handleLoadCompleted();
    453 
    454     // Have we completed before?
    455     if (m_isComplete)
    456         return;
    457 
    458     // Are we still parsing?
    459     if (m_frame->document()->parsing())
    460         return;
    461 
    462     // Still waiting for images/scripts?
    463     if (m_frame->document()->fetcher()->requestCount())
    464         return;
    465 
    466     // Still waiting for elements that don't go through a FrameLoader?
    467     if (m_frame->document()->isDelayingLoadEvent())
    468         return;
    469 
    470     // Any frame that hasn't completed yet?
    471     if (!allChildrenAreComplete())
    472         return;
    473 
    474     // OK, completed.
    475     m_isComplete = true;
    476     m_frame->document()->setReadyState(Document::Complete);
    477     if (m_frame->document()->loadEventStillNeeded())
    478         m_frame->document()->implicitClose();
    479 
    480     m_frame->navigationScheduler().startTimer();
    481 
    482     completed();
    483     if (m_frame->page())
    484         checkLoadComplete();
    485 
    486     if (m_frame->view())
    487         m_frame->view()->handleLoadCompleted();
    488 }
    489 
    490 void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
    491 {
    492     RefPtr<Frame> protect(m_frame);
    493 
    494     if (Page* page = m_frame->page()) {
    495         if (page->defersLoading())
    496             return;
    497     }
    498     if (m_shouldCallCheckCompleted)
    499         checkCompleted();
    500 }
    501 
    502 void FrameLoader::startCheckCompleteTimer()
    503 {
    504     if (!m_shouldCallCheckCompleted)
    505         return;
    506     if (m_checkTimer.isActive())
    507         return;
    508     m_checkTimer.startOneShot(0);
    509 }
    510 
    511 void FrameLoader::scheduleCheckCompleted()
    512 {
    513     m_shouldCallCheckCompleted = true;
    514     startCheckCompleteTimer();
    515 }
    516 
    517 Frame* FrameLoader::opener()
    518 {
    519     return m_opener;
    520 }
    521 
    522 void FrameLoader::setOpener(Frame* opener)
    523 {
    524     if (m_opener && !opener)
    525         m_client->didDisownOpener();
    526 
    527     if (m_opener)
    528         m_opener->loader().m_openedFrames.remove(m_frame);
    529     if (opener)
    530         opener->loader().m_openedFrames.add(m_frame);
    531     m_opener = opener;
    532 
    533     if (m_frame->document())
    534         m_frame->document()->initSecurityContext();
    535 }
    536 
    537 bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason)
    538 {
    539     Settings* settings = m_frame->settings();
    540     bool allowed = m_client->allowPlugins(settings && settings->pluginsEnabled());
    541     if (!allowed && reason == AboutToInstantiatePlugin)
    542         m_client->didNotAllowPlugins();
    543     return allowed;
    544 }
    545 
    546 void FrameLoader::updateForSameDocumentNavigation(const KURL& newURL, SameDocumentNavigationSource sameDocumentNavigationSource, PassRefPtr<SerializedScriptValue> data, UpdateBackForwardListPolicy updateBackForwardList)
    547 {
    548     // Update the data source's request with the new URL to fake the URL change
    549     m_frame->document()->setURL(newURL);
    550     documentLoader()->updateForSameDocumentNavigation(newURL);
    551 
    552     // Generate start and stop notifications only when loader is completed so that we
    553     // don't fire them for fragment redirection that happens in window.onload handler.
    554     // See https://bugs.webkit.org/show_bug.cgi?id=31838
    555     if (m_frame->document()->loadEventFinished())
    556         m_client->postProgressStartedNotification();
    557 
    558     NavigationHistoryPolicy navigationHistoryPolicy = NavigationReusedHistoryEntry;
    559     if (updateBackForwardList == UpdateBackForwardList || (sameDocumentNavigationSource == SameDocumentNavigationPushState && m_currentItem)) {
    560         navigationHistoryPolicy = NavigationCreatedHistoryEntry;
    561         setHistoryItemStateForCommit(CreateNewHistoryItem);
    562     }
    563     m_client->dispatchDidNavigateWithinPage(navigationHistoryPolicy, m_currentItem.get());
    564     m_client->dispatchDidReceiveTitle(m_frame->document()->title());
    565 
    566     if (m_currentItem) {
    567         m_currentItem->setURL(newURL);
    568         if (sameDocumentNavigationSource != SameDocumentNavigationDefault) {
    569             m_currentItem->setStateObject(data);
    570             m_currentItem->setFormData(0);
    571             m_currentItem->setFormContentType(nullAtom);
    572         }
    573     }
    574 
    575     if (m_frame->document()->loadEventFinished())
    576         m_client->postProgressFinishedNotification();
    577 }
    578 
    579 void FrameLoader::loadInSameDocument(const KURL& url, PassRefPtr<SerializedScriptValue> stateObject, bool isNewNavigation, ClientRedirectPolicy clientRedirect)
    580 {
    581     // If we have a state object, we cannot also be a new navigation.
    582     ASSERT(!stateObject || (stateObject && !isNewNavigation));
    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 && !isNewNavigation) || !UserGestureIndicator::processingUserGesture());
    592     m_documentLoader->setReplacesCurrentHistoryItem(!isNewNavigation);
    593     UpdateBackForwardListPolicy updateBackForwardList = isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject ? UpdateBackForwardList : DoNotUpdateBackForwardList;
    594     updateForSameDocumentNavigation(url, SameDocumentNavigationDefault, 0, updateBackForwardList);
    595 
    596     // It's important to model this as a load that starts and immediately finishes.
    597     // Otherwise, the parent frame may think we never finished loading.
    598     started();
    599 
    600     // We need to scroll to the fragment whether or not a hash change occurred, since
    601     // the user might have scrolled since the previous navigation.
    602     scrollToFragmentWithParentBoundary(url);
    603 
    604     m_isComplete = false;
    605     checkCompleted();
    606 
    607     m_frame->domWindow()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue());
    608 }
    609 
    610 void FrameLoader::completed()
    611 {
    612     RefPtr<Frame> protect(m_frame);
    613 
    614     for (Frame* descendant = m_frame->tree().traverseNext(m_frame); descendant; descendant = descendant->tree().traverseNext(m_frame))
    615         descendant->navigationScheduler().startTimer();
    616 
    617     if (Frame* parent = m_frame->tree().parent())
    618         parent->loader().checkCompleted();
    619 
    620     if (m_frame->view())
    621         m_frame->view()->maintainScrollPositionAtAnchor(0);
    622 }
    623 
    624 void FrameLoader::started()
    625 {
    626     for (Frame* frame = m_frame; frame; frame = frame->tree().parent())
    627         frame->loader().m_isComplete = false;
    628 }
    629 
    630 void FrameLoader::setReferrerForFrameRequest(ResourceRequest& request, ShouldSendReferrer shouldSendReferrer, Document* originDocument)
    631 {
    632     if (shouldSendReferrer == NeverSendReferrer) {
    633         request.clearHTTPReferrer();
    634         return;
    635     }
    636 
    637     // Always use the initiating document to generate the referrer.
    638     // We need to generateReferrerHeader(), because we might not have enforced ReferrerPolicy or https->http
    639     // referrer suppression yet.
    640     String argsReferrer(request.httpReferrer());
    641     if (argsReferrer.isEmpty())
    642         argsReferrer = originDocument->outgoingReferrer();
    643     String referrer = SecurityPolicy::generateReferrerHeader(originDocument->referrerPolicy(), request.url(), argsReferrer);
    644 
    645     request.setHTTPReferrer(referrer);
    646     RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
    647     addHTTPOriginIfNeeded(request, referrerOrigin->toString());
    648 }
    649 
    650 bool FrameLoader::isScriptTriggeredFormSubmissionInChildFrame(const FrameLoadRequest& request) const
    651 {
    652     // If this is a child frame and the form submission was triggered by a script, lock the back/forward list
    653     // to match IE and Opera.
    654     // See https://bugs.webkit.org/show_bug.cgi?id=32383 for the original motivation for this.
    655     if (!m_frame->tree().parent() || UserGestureIndicator::processingUserGesture())
    656         return false;
    657     return request.formState() && request.formState()->formSubmissionTrigger() == SubmittedByJavaScript;
    658 }
    659 
    660 FrameLoadType FrameLoader::determineFrameLoadType(const FrameLoadRequest& request)
    661 {
    662     if (m_frame->tree().parent() && !m_stateMachine.startedFirstRealLoad())
    663         return FrameLoadTypeInitialInChildFrame;
    664     if (!m_frame->tree().parent() && !m_frame->page()->backForward().backForwardListCount())
    665         return FrameLoadTypeStandard;
    666     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
    667         return FrameLoadTypeReload;
    668     if (request.lockBackForwardList() || isScriptTriggeredFormSubmissionInChildFrame(request))
    669         return FrameLoadTypeRedirectWithLockedBackForwardList;
    670     if (!request.originDocument() && shouldTreatURLAsSameAsCurrent(request.resourceRequest().url()))
    671         return FrameLoadTypeSame;
    672     if (shouldTreatURLAsSameAsCurrent(request.substituteData().failingURL()) && m_loadType == FrameLoadTypeReload)
    673         return FrameLoadTypeReload;
    674     return FrameLoadTypeStandard;
    675 }
    676 
    677 bool FrameLoader::prepareRequestForThisFrame(FrameLoadRequest& request)
    678 {
    679     // If no origin Document* was specified, skip security checks and assume the caller has fully initialized the FrameLoadRequest.
    680     if (!request.originDocument())
    681         return true;
    682 
    683     KURL url = request.resourceRequest().url();
    684     if (m_frame->script().executeScriptIfJavaScriptURL(url))
    685         return false;
    686 
    687     if (!request.originDocument()->securityOrigin()->canDisplay(url)) {
    688         reportLocalLoadFailed(m_frame, url.elidedString());
    689         return false;
    690     }
    691 
    692     if (!request.formState() && request.frameName().isEmpty())
    693         request.setFrameName(m_frame->document()->baseTarget());
    694 
    695     setReferrerForFrameRequest(request.resourceRequest(), request.shouldSendReferrer(), request.originDocument());
    696     return true;
    697 }
    698 
    699 void FrameLoader::load(const FrameLoadRequest& passedRequest)
    700 {
    701     ASSERT(m_frame->document());
    702 
    703     // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader.
    704     RefPtr<Frame> protect(m_frame);
    705 
    706     if (m_inStopAllLoaders)
    707         return;
    708 
    709     FrameLoadRequest request(passedRequest);
    710     if (!prepareRequestForThisFrame(request))
    711         return;
    712 
    713     RefPtr<Frame> targetFrame = request.formState() ? 0 : findFrameForNavigation(request.frameName(), request.formState() ? request.formState()->sourceDocument() : m_frame->document());
    714     if (targetFrame && targetFrame != m_frame) {
    715         request.setFrameName("_self");
    716         targetFrame->loader().load(request);
    717         if (Page* page = targetFrame->page())
    718             page->chrome().focus();
    719         return;
    720     }
    721 
    722     FrameLoadType newLoadType = determineFrameLoadType(request);
    723     NavigationAction action(request.resourceRequest(), newLoadType, request.formState(), request.triggeringEvent());
    724     if ((!targetFrame && !request.frameName().isEmpty()) || action.shouldOpenInNewWindow()) {
    725         if (action.policy() == NavigationPolicyDownload)
    726             m_client->loadURLExternally(action.resourceRequest(), NavigationPolicyDownload);
    727         else
    728             createWindowForRequest(request, m_frame, action.policy(), request.shouldSendReferrer());
    729         return;
    730     }
    731 
    732     if (shouldPerformFragmentNavigation(request.formState(), request.resourceRequest().httpMethod(), newLoadType, request.resourceRequest().url())) {
    733         checkNavigationPolicyAndContinueFragmentScroll(action, newLoadType != FrameLoadTypeRedirectWithLockedBackForwardList, request.clientRedirect());
    734         return;
    735     }
    736     bool sameURL = shouldTreatURLAsSameAsCurrent(request.resourceRequest().url());
    737     loadWithNavigationAction(action, newLoadType, request.formState(), request.substituteData(), request.clientRedirect());
    738     // Example of this case are sites that reload the same URL with a different cookie
    739     // driving the generated content, or a master frame with links that drive a target
    740     // frame, where the user has clicked on the same link repeatedly.
    741     if (sameURL && newLoadType != FrameLoadTypeReload && newLoadType != FrameLoadTypeReloadFromOrigin && request.resourceRequest().httpMethod() != "POST")
    742         m_loadType = FrameLoadTypeSame;
    743 }
    744 
    745 SubstituteData FrameLoader::defaultSubstituteDataForURL(const KURL& url)
    746 {
    747     if (!shouldTreatURLAsSrcdocDocument(url))
    748         return SubstituteData();
    749     String srcdoc = m_frame->ownerElement()->fastGetAttribute(srcdocAttr);
    750     ASSERT(!srcdoc.isNull());
    751     CString encodedSrcdoc = srcdoc.utf8();
    752     return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), "text/html", "UTF-8", KURL());
    753 }
    754 
    755 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
    756 {
    757     ASSERT(!url.isEmpty());
    758     if (!frame)
    759         return;
    760 
    761     frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url);
    762 }
    763 
    764 void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const AtomicString& overrideEncoding)
    765 {
    766     DocumentLoader* documentLoader = activeDocumentLoader();
    767     if (!documentLoader)
    768         return;
    769 
    770     ResourceRequest request = documentLoader->request();
    771     // FIXME: We need to reset cache policy to prevent it from being incorrectly propagted to the reload.
    772     // Do we need to propagate anything other than the url?
    773     request.setCachePolicy(UseProtocolCachePolicy);
    774     if (!overrideURL.isEmpty())
    775         request.setURL(overrideURL);
    776     else if (!documentLoader->unreachableURL().isEmpty())
    777         request.setURL(documentLoader->unreachableURL());
    778 
    779     FrameLoadType type = reloadPolicy == EndToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload;
    780     NavigationAction action(request, type, request.httpMethod() == "POST");
    781     loadWithNavigationAction(action, type, 0, SubstituteData(), NotClientRedirect, overrideEncoding);
    782 }
    783 
    784 void FrameLoader::stopAllLoaders()
    785 {
    786     if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal)
    787         return;
    788 
    789     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
    790     if (m_inStopAllLoaders)
    791         return;
    792 
    793     // Calling stopLoading() on the provisional document loader can blow away
    794     // the frame from underneath.
    795     RefPtr<Frame> protect(m_frame);
    796 
    797     m_inStopAllLoaders = true;
    798 
    799     for (RefPtr<Frame> child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling())
    800         child->loader().stopAllLoaders();
    801     if (m_provisionalDocumentLoader)
    802         m_provisionalDocumentLoader->stopLoading();
    803     if (m_documentLoader)
    804         m_documentLoader->stopLoading();
    805 
    806     if (m_provisionalDocumentLoader)
    807         m_provisionalDocumentLoader->detachFromFrame();
    808     m_provisionalDocumentLoader = 0;
    809 
    810     m_checkTimer.stop();
    811 
    812     m_inStopAllLoaders = false;
    813 
    814     m_client->didStopAllLoaders();
    815 }
    816 
    817 DocumentLoader* FrameLoader::activeDocumentLoader() const
    818 {
    819     if (m_state == FrameStateProvisional)
    820         return m_provisionalDocumentLoader.get();
    821     return m_documentLoader.get();
    822 }
    823 
    824 void FrameLoader::didAccessInitialDocument()
    825 {
    826     // We only need to notify the client once, and only for the main frame.
    827     if (isLoadingMainFrame() && !m_didAccessInitialDocument) {
    828         m_didAccessInitialDocument = true;
    829         // Notify asynchronously, since this is called within a JavaScript security check.
    830         m_didAccessInitialDocumentTimer.startOneShot(0);
    831     }
    832 }
    833 
    834 void FrameLoader::didAccessInitialDocumentTimerFired(Timer<FrameLoader>*)
    835 {
    836     m_client->didAccessInitialDocument();
    837 }
    838 
    839 void FrameLoader::notifyIfInitialDocumentAccessed()
    840 {
    841     if (m_didAccessInitialDocumentTimer.isActive()) {
    842         m_didAccessInitialDocumentTimer.stop();
    843         didAccessInitialDocumentTimerFired(0);
    844     }
    845 }
    846 
    847 bool FrameLoader::isLoading() const
    848 {
    849     DocumentLoader* docLoader = activeDocumentLoader();
    850     if (!docLoader)
    851         return false;
    852     return docLoader->isLoading();
    853 }
    854 
    855 void FrameLoader::commitProvisionalLoad()
    856 {
    857     ASSERT(m_client->hasWebView());
    858     ASSERT(m_state == FrameStateProvisional);
    859     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
    860     RefPtr<Frame> protect(m_frame);
    861 
    862     closeOldDataSources();
    863 
    864     // Check if the destination page is allowed to access the previous page's timing information.
    865     if (m_frame->document()) {
    866         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(pdl->request().url());
    867         pdl->timing()->setHasSameOriginAsPreviousDocument(securityOrigin->canRequest(m_frame->document()->url()));
    868     }
    869 
    870     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
    871     // JavaScript. If the script initiates a new load, we need to abandon the current load,
    872     // or the two will stomp each other.
    873     // detachChildren will similarly trigger child frame unload event handlers.
    874     if (m_documentLoader)
    875         closeURL();
    876     detachChildren();
    877     if (pdl != m_provisionalDocumentLoader)
    878         return;
    879     if (m_documentLoader)
    880         m_documentLoader->detachFromFrame();
    881     m_documentLoader = m_provisionalDocumentLoader.release();
    882     m_state = FrameStateCommittedPage;
    883 
    884     if (isLoadingMainFrame())
    885         m_frame->page()->chrome().client().needTouchEvents(false);
    886 
    887     m_client->transitionToCommittedForNewPage();
    888     m_frame->navigationScheduler().cancel();
    889     m_frame->editor().clearLastEditCommand();
    890 
    891     // If we are still in the process of initializing an empty document then
    892     // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
    893     // since it may cause clients to attempt to render the frame.
    894     if (!m_stateMachine.creatingInitialEmptyDocument()) {
    895         DOMWindow* window = m_frame->domWindow();
    896         window->setStatus(String());
    897         window->setDefaultStatus(String());
    898     }
    899     started();
    900 }
    901 
    902 void FrameLoader::closeOldDataSources()
    903 {
    904     // FIXME: Is it important for this traversal to be postorder instead of preorder?
    905     // If so, add helpers for postorder traversal, and use them. If not, then lets not
    906     // use a recursive algorithm here.
    907     for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().nextSibling())
    908         child->loader().closeOldDataSources();
    909 
    910     if (m_documentLoader)
    911         m_client->dispatchWillClose();
    912 }
    913 
    914 bool FrameLoader::isLoadingMainFrame() const
    915 {
    916     return m_frame->isMainFrame();
    917 }
    918 
    919 bool FrameLoader::subframeIsLoading() const
    920 {
    921     // It's most likely that the last added frame is the last to load so we walk backwards.
    922     for (Frame* child = m_frame->tree().lastChild(); child; child = child->tree().previousSibling()) {
    923         const FrameLoader& childLoader = child->loader();
    924         DocumentLoader* documentLoader = childLoader.documentLoader();
    925         if (documentLoader && documentLoader->isLoadingInAPISense())
    926             return true;
    927         documentLoader = childLoader.provisionalDocumentLoader();
    928         if (documentLoader && documentLoader->isLoadingInAPISense())
    929             return true;
    930         documentLoader = childLoader.policyDocumentLoader();
    931         if (documentLoader)
    932             return true;
    933     }
    934     return false;
    935 }
    936 
    937 FrameLoadType FrameLoader::loadType() const
    938 {
    939     return m_loadType;
    940 }
    941 
    942 void FrameLoader::checkLoadCompleteForThisFrame()
    943 {
    944     ASSERT(m_client->hasWebView());
    945 
    946     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
    947         const ResourceError& error = m_provisionalDocumentLoader->mainDocumentError();
    948         if (error.isNull())
    949             return;
    950         RefPtr<DocumentLoader> loader = m_provisionalDocumentLoader;
    951         m_client->dispatchDidFailProvisionalLoad(error);
    952         if (loader != m_provisionalDocumentLoader)
    953             return;
    954         m_provisionalDocumentLoader->detachFromFrame();
    955         m_provisionalDocumentLoader = 0;
    956         m_progressTracker->progressCompleted();
    957         m_state = FrameStateComplete;
    958     }
    959 
    960     if (m_state != FrameStateCommittedPage)
    961         return;
    962 
    963     if (!m_documentLoader || (m_documentLoader->isLoadingInAPISense() && !m_inStopAllLoaders))
    964         return;
    965 
    966     m_state = FrameStateComplete;
    967 
    968     // FIXME: Is this subsequent work important if we already navigated away?
    969     // Maybe there are bugs because of that, or extra work we can skip because
    970     // the new page is ready.
    971 
    972     // If the user had a scroll point, scroll to it, overriding the anchor point if any.
    973     restoreScrollPositionAndViewState();
    974 
    975     if (!m_stateMachine.committedFirstRealDocumentLoad())
    976         return;
    977 
    978     m_progressTracker->progressCompleted();
    979 
    980     const ResourceError& error = m_documentLoader->mainDocumentError();
    981     if (!error.isNull())
    982         m_client->dispatchDidFailLoad(error);
    983     else
    984         m_client->dispatchDidFinishLoad();
    985     m_loadType = FrameLoadTypeStandard;
    986 }
    987 
    988 // There is a race condition between the layout and load completion that affects restoring the scroll position.
    989 // We try to restore the scroll position at both the first layout and upon load completion.
    990 // 1) If first layout happens before the load completes, we want to restore the scroll position then so that the
    991 // first time we draw the page is already scrolled to the right place, instead of starting at the top and later
    992 // jumping down. It is possible that the old scroll position is past the part of the doc laid out so far, in
    993 // which case the restore silent fails and we will fix it in when we try to restore on doc completion.
    994 // 2) If the layout happens after the load completes, the attempt to restore at load completion time silently
    995 // fails. We then successfully restore it when the layout happens.
    996 void FrameLoader::restoreScrollPositionAndViewState(RestorePolicy restorePolicy)
    997 {
    998     if (!isBackForwardLoadType(m_loadType) && m_loadType != FrameLoadTypeReload && m_loadType != FrameLoadTypeReloadFromOrigin && restorePolicy != ForcedRestoreForSameDocumentHistoryNavigation)
    999         return;
   1000     if (!m_frame->page() || !m_currentItem || !m_stateMachine.committedFirstRealDocumentLoad())
   1001         return;
   1002 
   1003     if (FrameView* view = m_frame->view()) {
   1004         if (m_frame->isMainFrame()) {
   1005             if (ScrollingCoordinator* scrollingCoordinator = m_frame->page()->scrollingCoordinator())
   1006                 scrollingCoordinator->frameViewRootLayerDidChange(view);
   1007         }
   1008 
   1009         if (!view->wasScrolledByUser() || restorePolicy == ForcedRestoreForSameDocumentHistoryNavigation) {
   1010             if (m_frame->isMainFrame() && m_currentItem->pageScaleFactor())
   1011                 m_frame->page()->setPageScaleFactor(m_currentItem->pageScaleFactor(), m_currentItem->scrollPoint());
   1012             else
   1013                 view->setScrollPositionNonProgrammatically(m_currentItem->scrollPoint());
   1014         }
   1015     }
   1016 }
   1017 
   1018 void FrameLoader::didFirstLayout()
   1019 {
   1020     restoreScrollPositionAndViewState();
   1021 }
   1022 
   1023 void FrameLoader::detachChildren()
   1024 {
   1025     typedef Vector<RefPtr<Frame> > FrameVector;
   1026     FrameVector childrenToDetach;
   1027     childrenToDetach.reserveCapacity(m_frame->tree().childCount());
   1028     for (Frame* child = m_frame->tree().lastChild(); child; child = child->tree().previousSibling())
   1029         childrenToDetach.append(child);
   1030     FrameVector::iterator end = childrenToDetach.end();
   1031     for (FrameVector::iterator it = childrenToDetach.begin(); it != end; it++)
   1032         (*it)->loader().detachFromParent();
   1033 }
   1034 
   1035 void FrameLoader::closeAndRemoveChild(Frame* child)
   1036 {
   1037     child->tree().detachFromParent();
   1038 
   1039     child->setView(0);
   1040     if (child->ownerElement() && child->page())
   1041         child->page()->decrementSubframeCount();
   1042     child->willDetachPage();
   1043     child->detachFromPage();
   1044 
   1045     m_frame->tree().removeChild(child);
   1046 }
   1047 
   1048 // Called every time a resource is completely loaded or an error is received.
   1049 void FrameLoader::checkLoadComplete()
   1050 {
   1051     ASSERT(m_client->hasWebView());
   1052 
   1053     // FIXME: Always traversing the entire frame tree is a bit inefficient, but
   1054     // is currently needed in order to null out the previous history item for all frames.
   1055     if (Page* page = m_frame->page()) {
   1056         Vector<RefPtr<Frame>, 10> frames;
   1057         for (RefPtr<Frame> frame = page->mainFrame(); frame; frame = frame->tree().traverseNext())
   1058             frames.append(frame);
   1059         // To process children before their parents, iterate the vector backwards.
   1060         for (size_t i = frames.size(); i; --i)
   1061             frames[i - 1]->loader().checkLoadCompleteForThisFrame();
   1062     }
   1063 }
   1064 
   1065 void FrameLoader::checkLoadComplete(DocumentLoader* documentLoader)
   1066 {
   1067     if (documentLoader)
   1068         documentLoader->checkLoadComplete();
   1069     checkLoadComplete();
   1070 }
   1071 
   1072 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
   1073 {
   1074     if (!recurse)
   1075         return m_frame->document()->fetcher()->requestCount();
   1076 
   1077     int count = 0;
   1078     for (Frame* frame = m_frame; frame; frame = frame->tree().traverseNext(m_frame))
   1079         count += frame->document()->fetcher()->requestCount();
   1080     return count;
   1081 }
   1082 
   1083 String FrameLoader::userAgent(const KURL& url) const
   1084 {
   1085     String userAgent = m_client->userAgent(url);
   1086     InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent);
   1087     return userAgent;
   1088 }
   1089 
   1090 void FrameLoader::frameDetached()
   1091 {
   1092     // stopAllLoaders can detach the Frame, so protect it.
   1093     RefPtr<Frame> protect(m_frame);
   1094     stopAllLoaders();
   1095     detachFromParent();
   1096 }
   1097 
   1098 void FrameLoader::detachFromParent()
   1099 {
   1100     // stopAllLoaders can detach the Frame, so protect it.
   1101     RefPtr<Frame> protect(m_frame);
   1102 
   1103     closeURL();
   1104     detachChildren();
   1105     // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren()
   1106     // will trigger the unload event handlers of any child frames, and those event
   1107     // handlers might start a new subresource load in this frame.
   1108     stopAllLoaders();
   1109 
   1110     InspectorInstrumentation::frameDetachedFromParent(m_frame);
   1111 
   1112     if (m_documentLoader)
   1113         m_documentLoader->detachFromFrame();
   1114     m_documentLoader = 0;
   1115     m_client->detachedFromParent();
   1116 
   1117     m_progressTracker.clear();
   1118 
   1119     if (Frame* parent = m_frame->tree().parent()) {
   1120         parent->loader().closeAndRemoveChild(m_frame);
   1121         parent->loader().scheduleCheckCompleted();
   1122     } else {
   1123         m_frame->setView(0);
   1124         m_frame->willDetachPage();
   1125         m_frame->detachFromPage();
   1126     }
   1127 }
   1128 
   1129 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request)
   1130 {
   1131     bool isMainResource = (request.targetType() == ResourceRequest::TargetIsMainFrame) || (request.targetType() == ResourceRequest::TargetIsSubframe);
   1132 
   1133     if (isMainResource && isLoadingMainFrame())
   1134         request.setFirstPartyForCookies(request.url());
   1135     else
   1136         request.setFirstPartyForCookies(m_frame->document()->firstPartyForCookies());
   1137 
   1138     // The remaining modifications are only necessary for HTTP and HTTPS.
   1139     if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
   1140         return;
   1141 
   1142     applyUserAgent(request);
   1143 
   1144     if (request.cachePolicy() == ReloadIgnoringCacheData) {
   1145         if (m_loadType == FrameLoadTypeReload)
   1146             request.setHTTPHeaderField("Cache-Control", "max-age=0");
   1147         else if (m_loadType == FrameLoadTypeReloadFromOrigin) {
   1148             request.setHTTPHeaderField("Cache-Control", "no-cache");
   1149             request.setHTTPHeaderField("Pragma", "no-cache");
   1150         }
   1151     }
   1152 
   1153     if (isMainResource)
   1154         request.setHTTPAccept(defaultAcceptHeader);
   1155 
   1156     // Make sure we send the Origin header.
   1157     addHTTPOriginIfNeeded(request, nullAtom);
   1158 }
   1159 
   1160 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const AtomicString& origin)
   1161 {
   1162     if (!request.httpOrigin().isEmpty())
   1163         return;  // Request already has an Origin header.
   1164 
   1165     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
   1166     // For example, if an intranet page has a hyperlink to an external web
   1167     // site, we don't want to include the Origin of the request because it
   1168     // will leak the internal host name. Similar privacy concerns have lead
   1169     // to the widespread suppression of the Referer header at the network
   1170     // layer.
   1171     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
   1172         return;
   1173 
   1174     // For non-GET and non-HEAD methods, always send an Origin header so the
   1175     // server knows we support this feature.
   1176 
   1177     if (origin.isEmpty()) {
   1178         // If we don't know what origin header to attach, we attach the value
   1179         // for an empty origin.
   1180         request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
   1181         return;
   1182     }
   1183 
   1184     request.setHTTPOrigin(origin);
   1185 }
   1186 
   1187 const ResourceRequest& FrameLoader::originalRequest() const
   1188 {
   1189     return activeDocumentLoader()->originalRequestCopy();
   1190 }
   1191 
   1192 void FrameLoader::receivedMainResourceError(const ResourceError& error)
   1193 {
   1194     // Retain because the stop may release the last reference to it.
   1195     RefPtr<Frame> protect(m_frame);
   1196 
   1197     RefPtr<DocumentLoader> loader = activeDocumentLoader();
   1198     if (m_frame->document()->parser())
   1199         m_frame->document()->parser()->stopParsing();
   1200 
   1201     // FIXME: We really ought to be able to just check for isCancellation() here, but there are some
   1202     // ResourceErrors that setIsCancellation() but aren't created by ResourceError::cancelledError().
   1203     ResourceError c(ResourceError::cancelledError(KURL()));
   1204     if ((error.errorCode() != c.errorCode() || error.domain() != c.domain()) && m_frame->ownerElement())
   1205         m_frame->ownerElement()->renderFallbackContent();
   1206 
   1207     checkCompleted();
   1208     if (m_frame->page())
   1209         checkLoadComplete();
   1210 }
   1211 
   1212 void FrameLoader::checkNavigationPolicyAndContinueFragmentScroll(const NavigationAction& action, bool isNewNavigation, ClientRedirectPolicy clientRedirect)
   1213 {
   1214     m_documentLoader->setTriggeringAction(action);
   1215 
   1216     const ResourceRequest& request = action.resourceRequest();
   1217     if (!m_documentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckFragment))
   1218         return;
   1219 
   1220     // If we have a provisional request for a different document, a fragment scroll should cancel it.
   1221     if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
   1222         m_provisionalDocumentLoader->stopLoading();
   1223         if (m_provisionalDocumentLoader)
   1224             m_provisionalDocumentLoader->detachFromFrame();
   1225         m_provisionalDocumentLoader = 0;
   1226     }
   1227     saveDocumentAndScrollState();
   1228     loadInSameDocument(request.url(), 0, isNewNavigation, clientRedirect);
   1229 }
   1230 
   1231 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url)
   1232 {
   1233     ASSERT(loadType != FrameLoadTypeBackForward);
   1234     ASSERT(loadType != FrameLoadTypeReloadFromOrigin);
   1235     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
   1236     // currently displaying a frameset, or if the URL does not have a fragment.
   1237     return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET"))
   1238         && loadType != FrameLoadTypeReload
   1239         && loadType != FrameLoadTypeSame
   1240         && url.hasFragmentIdentifier()
   1241         && equalIgnoringFragmentIdentifier(m_frame->document()->url(), url)
   1242         // We don't want to just scroll if a link from within a
   1243         // frameset is trying to reload the frameset into _top.
   1244         && !m_frame->document()->isFrameSet();
   1245 }
   1246 
   1247 void FrameLoader::scrollToFragmentWithParentBoundary(const KURL& url)
   1248 {
   1249     FrameView* view = m_frame->view();
   1250     if (!view)
   1251         return;
   1252 
   1253     // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
   1254     RefPtr<Frame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame->document()->findUnsafeParentScrollPropagationBoundary() : 0);
   1255 
   1256     if (boundaryFrame)
   1257         boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
   1258 
   1259     view->scrollToFragment(url);
   1260 
   1261     if (boundaryFrame)
   1262         boundaryFrame->view()->setSafeToPropagateScrollToParent(true);
   1263 }
   1264 
   1265 bool FrameLoader::shouldClose()
   1266 {
   1267     Page* page = m_frame->page();
   1268     if (!page || !page->chrome().canRunBeforeUnloadConfirmPanel())
   1269         return true;
   1270 
   1271     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
   1272     Vector<RefPtr<Frame> > targetFrames;
   1273     targetFrames.append(m_frame);
   1274     for (Frame* child = m_frame->tree().firstChild(); child; child = child->tree().traverseNext(m_frame))
   1275         targetFrames.append(child);
   1276 
   1277     bool shouldClose = false;
   1278     {
   1279         NavigationDisablerForBeforeUnload navigationDisabler;
   1280         size_t i;
   1281 
   1282         bool didAllowNavigation = false;
   1283         for (i = 0; i < targetFrames.size(); i++) {
   1284             if (!targetFrames[i]->tree().isDescendantOf(m_frame))
   1285                 continue;
   1286             if (!targetFrames[i]->document()->dispatchBeforeUnloadEvent(page->chrome(), didAllowNavigation))
   1287                 break;
   1288         }
   1289 
   1290         if (i == targetFrames.size())
   1291             shouldClose = true;
   1292     }
   1293     return shouldClose;
   1294 }
   1295 
   1296 void FrameLoader::loadWithNavigationAction(const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState, const SubstituteData& substituteData, ClientRedirectPolicy clientRedirect, const AtomicString& overrideEncoding)
   1297 {
   1298     ASSERT(m_client->hasWebView());
   1299     if (m_frame->document()->pageDismissalEventBeingDispatched() != Document::NoDismissal)
   1300         return;
   1301 
   1302     // We skip dispatching the beforeload event on the frame owner if we've already committed a real
   1303     // document load because the event would leak subsequent activity by the frame which the parent
   1304     // frame isn't supposed to learn. For example, if the child frame navigated to  a new URL, the
   1305     // parent frame shouldn't learn the URL.
   1306     const ResourceRequest& request = action.resourceRequest();
   1307     if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame->ownerElement() && !m_frame->ownerElement()->dispatchBeforeLoadEvent(request.url().string()))
   1308         return;
   1309 
   1310     if (!m_stateMachine.startedFirstRealLoad())
   1311         m_stateMachine.advanceTo(FrameLoaderStateMachine::StartedFirstRealLoad);
   1312 
   1313     // The current load should replace the history item if it is the first real
   1314     // load of the frame.
   1315     bool replacesCurrentHistoryItem = false;
   1316     if (type == FrameLoadTypeRedirectWithLockedBackForwardList
   1317         || !m_stateMachine.committedFirstRealDocumentLoad()) {
   1318         replacesCurrentHistoryItem = true;
   1319     }
   1320 
   1321     m_policyDocumentLoader = m_client->createDocumentLoader(request, substituteData.isValid() ? substituteData : defaultSubstituteDataForURL(request.url()));
   1322     m_policyDocumentLoader->setFrame(m_frame);
   1323     m_policyDocumentLoader->setTriggeringAction(action);
   1324     m_policyDocumentLoader->setReplacesCurrentHistoryItem(replacesCurrentHistoryItem);
   1325     m_policyDocumentLoader->setIsClientRedirect(clientRedirect == ClientRedirect);
   1326 
   1327     if (Frame* parent = m_frame->tree().parent())
   1328         m_policyDocumentLoader->setOverrideEncoding(parent->loader().documentLoader()->overrideEncoding());
   1329     else if (!overrideEncoding.isEmpty())
   1330         m_policyDocumentLoader->setOverrideEncoding(overrideEncoding);
   1331     else if (m_documentLoader)
   1332         m_policyDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   1333 
   1334     // stopAllLoaders can detach the Frame, so protect it.
   1335     RefPtr<Frame> protect(m_frame);
   1336     if ((!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckStandard) || !shouldClose()) && m_policyDocumentLoader) {
   1337         m_policyDocumentLoader->detachFromFrame();
   1338         m_policyDocumentLoader = 0;
   1339         return;
   1340     }
   1341 
   1342     // A new navigation is in progress, so don't clear the history's provisional item.
   1343     stopAllLoaders();
   1344 
   1345     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
   1346     // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
   1347     if (!m_frame->page() || !m_policyDocumentLoader)
   1348         return;
   1349 
   1350     if (isLoadingMainFrame())
   1351         m_frame->page()->inspectorController().resume();
   1352     m_frame->navigationScheduler().cancel();
   1353 
   1354     m_provisionalDocumentLoader = m_policyDocumentLoader.release();
   1355     m_loadType = type;
   1356     m_state = FrameStateProvisional;
   1357 
   1358     if (formState)
   1359         m_client->dispatchWillSubmitForm(formState);
   1360 
   1361     m_progressTracker->progressStarted();
   1362     if (m_provisionalDocumentLoader->isClientRedirect())
   1363         m_provisionalDocumentLoader->appendRedirect(m_frame->document()->url());
   1364     m_provisionalDocumentLoader->appendRedirect(m_provisionalDocumentLoader->request().url());
   1365     m_client->dispatchDidStartProvisionalLoad();
   1366     ASSERT(m_provisionalDocumentLoader);
   1367     m_provisionalDocumentLoader->startLoadingMainResource();
   1368 }
   1369 
   1370 void FrameLoader::applyUserAgent(ResourceRequest& request)
   1371 {
   1372     String userAgent = this->userAgent(request.url());
   1373     ASSERT(!userAgent.isNull());
   1374     request.setHTTPUserAgent(userAgent);
   1375 }
   1376 
   1377 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url, unsigned long requestIdentifier)
   1378 {
   1379     UseCounter::count(m_frame->domWindow(), UseCounter::XFrameOptions);
   1380 
   1381     Frame* topFrame = m_frame->tree().top();
   1382     if (m_frame == topFrame)
   1383         return false;
   1384 
   1385     XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
   1386 
   1387     switch (disposition) {
   1388     case XFrameOptionsSameOrigin: {
   1389         UseCounter::count(m_frame->domWindow(), UseCounter::XFrameOptionsSameOrigin);
   1390         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
   1391         if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin()))
   1392             return true;
   1393         for (Frame* frame = m_frame->tree().parent(); frame; frame = frame->tree().parent()) {
   1394             if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin())) {
   1395                 UseCounter::count(m_frame->domWindow(), UseCounter::XFrameOptionsSameOriginWithBadAncestorChain);
   1396                 break;
   1397             }
   1398         }
   1399         return false;
   1400     }
   1401     case XFrameOptionsDeny:
   1402         return true;
   1403     case XFrameOptionsAllowAll:
   1404         return false;
   1405     case XFrameOptionsConflict:
   1406         m_frame->document()->addConsoleMessageWithRequestIdentifier(JSMessageSource, ErrorMessageLevel, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.elidedString() + "'. Falling back to 'DENY'.", requestIdentifier);
   1407         return true;
   1408     case XFrameOptionsInvalid:
   1409         m_frame->document()->addConsoleMessageWithRequestIdentifier(JSMessageSource, ErrorMessageLevel, "Invalid 'X-Frame-Options' header encountered when loading '" + url.elidedString() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier);
   1410         return false;
   1411     default:
   1412         ASSERT_NOT_REACHED();
   1413         return false;
   1414     }
   1415 }
   1416 
   1417 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
   1418 {
   1419     if (!m_currentItem)
   1420         return false;
   1421     return url == m_currentItem->url() || url == m_currentItem->originalURL();
   1422 }
   1423 
   1424 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const KURL& url) const
   1425 {
   1426     if (!equalIgnoringCase(url.string(), "about:srcdoc"))
   1427         return false;
   1428     HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
   1429     if (!ownerElement)
   1430         return false;
   1431     if (!ownerElement->hasTagName(iframeTag))
   1432         return false;
   1433     return ownerElement->fastHasAttribute(srcdocAttr);
   1434 }
   1435 
   1436 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
   1437 {
   1438     ASSERT(activeDocument);
   1439     Frame* frame = m_frame->tree().find(name);
   1440 
   1441     // From http://www.whatwg.org/specs/web-apps/current-work/#seamlessLinks:
   1442     //
   1443     // If the source browsing context is the same as the browsing context
   1444     // being navigated, and this browsing context has its seamless browsing
   1445     // context flag set, and the browsing context being navigated was not
   1446     // chosen using an explicit self-navigation override, then find the
   1447     // nearest ancestor browsing context that does not have its seamless
   1448     // browsing context flag set, and continue these steps as if that
   1449     // browsing context was the one that was going to be navigated instead.
   1450     if (frame == m_frame && name != "_self" && m_frame->document()->shouldDisplaySeamlesslyWithParent()) {
   1451         for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree().parent()) {
   1452             if (!ancestor->document()->shouldDisplaySeamlesslyWithParent()) {
   1453                 frame = ancestor;
   1454                 break;
   1455             }
   1456         }
   1457         ASSERT(frame != m_frame);
   1458     }
   1459 
   1460     if (!activeDocument->canNavigate(frame))
   1461         return 0;
   1462     return frame;
   1463 }
   1464 
   1465 void FrameLoader::loadHistoryItem(HistoryItem* item, HistoryLoadType historyLoadType)
   1466 {
   1467     saveDocumentAndScrollState();
   1468     m_currentItem = item;
   1469     if (historyLoadType == HistorySameDocumentLoad) {
   1470         loadInSameDocument(item->url(), item->stateObject(), false, NotClientRedirect);
   1471         restoreScrollPositionAndViewState(ForcedRestoreForSameDocumentHistoryNavigation);
   1472         return;
   1473     }
   1474 
   1475     RefPtr<FormData> formData = item->formData();
   1476     ResourceRequest request(item->url());
   1477     request.setHTTPReferrer(item->referrer());
   1478     if (formData) {
   1479         request.setHTTPMethod("POST");
   1480         request.setHTTPBody(formData);
   1481         request.setHTTPContentType(item->formContentType());
   1482         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer());
   1483         addHTTPOriginIfNeeded(request, securityOrigin->toString());
   1484     }
   1485 
   1486     loadWithNavigationAction(NavigationAction(request, FrameLoadTypeBackForward, formData), FrameLoadTypeBackForward, 0, SubstituteData());
   1487 }
   1488 
   1489 void FrameLoader::dispatchDocumentElementAvailable()
   1490 {
   1491     m_client->documentElementAvailable();
   1492 }
   1493 
   1494 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
   1495 {
   1496     if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript))
   1497         return;
   1498 
   1499     Vector<RefPtr<DOMWrapperWorld> > worlds;
   1500     DOMWrapperWorld::getAllWorlds(worlds);
   1501     for (size_t i = 0; i < worlds.size(); ++i)
   1502         dispatchDidClearWindowObjectInWorld(worlds[i].get());
   1503 }
   1504 
   1505 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
   1506 {
   1507     if (!m_frame->script().canExecuteScripts(NotAboutToExecuteScript) || !m_frame->script().existingWindowShell(world))
   1508         return;
   1509 
   1510     m_client->dispatchDidClearWindowObjectInWorld(world);
   1511 
   1512     if (Page* page = m_frame->page())
   1513         page->inspectorController().didClearWindowObjectInWorld(m_frame, world);
   1514 
   1515     InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
   1516 }
   1517 
   1518 SandboxFlags FrameLoader::effectiveSandboxFlags() const
   1519 {
   1520     SandboxFlags flags = m_forcedSandboxFlags;
   1521     if (Frame* parentFrame = m_frame->tree().parent())
   1522         flags |= parentFrame->document()->sandboxFlags();
   1523     if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement())
   1524         flags |= ownerElement->sandboxFlags();
   1525     return flags;
   1526 }
   1527 
   1528 } // namespace WebCore
   1529