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/BeforeUnloadEvent.h"
     43 #include "core/dom/Document.h"
     44 #include "core/dom/Element.h"
     45 #include "core/dom/Event.h"
     46 #include "core/dom/EventNames.h"
     47 #include "core/dom/PageTransitionEvent.h"
     48 #include "core/editing/Editor.h"
     49 #include "core/history/BackForwardController.h"
     50 #include "core/history/HistoryItem.h"
     51 #include "core/html/HTMLFormElement.h"
     52 #include "core/html/HTMLInputElement.h"
     53 #include "core/html/HTMLObjectElement.h"
     54 #include "core/html/parser/HTMLParserIdioms.h"
     55 #include "core/inspector/InspectorController.h"
     56 #include "core/inspector/InspectorInstrumentation.h"
     57 #include "core/loader/DocumentLoadTiming.h"
     58 #include "core/loader/DocumentLoader.h"
     59 #include "core/loader/FormState.h"
     60 #include "core/loader/FormSubmission.h"
     61 #include "core/loader/FrameLoadRequest.h"
     62 #include "core/loader/FrameLoaderClient.h"
     63 #include "core/loader/IconController.h"
     64 #include "core/loader/ProgressTracker.h"
     65 #include "core/loader/ResourceLoader.h"
     66 #include "core/loader/UniqueIdentifier.h"
     67 #include "core/loader/appcache/ApplicationCacheHost.h"
     68 #include "core/loader/cache/ResourceFetcher.h"
     69 #include "core/page/Chrome.h"
     70 #include "core/page/ChromeClient.h"
     71 #include "core/page/ContentSecurityPolicy.h"
     72 #include "core/page/ContentSecurityPolicyResponseHeaders.h"
     73 #include "core/page/DOMWindow.h"
     74 #include "core/page/EventHandler.h"
     75 #include "core/page/Frame.h"
     76 #include "core/page/FrameTree.h"
     77 #include "core/page/FrameView.h"
     78 #include "core/page/Page.h"
     79 #include "core/page/Settings.h"
     80 #include "core/page/WindowFeatures.h"
     81 #include "core/platform/Logging.h"
     82 #include "core/platform/ScrollAnimator.h"
     83 #include "core/platform/graphics/FloatRect.h"
     84 #include "core/platform/network/HTTPParsers.h"
     85 #include "core/platform/network/ResourceRequest.h"
     86 #include "core/xml/parser/XMLDocumentParser.h"
     87 #include "modules/webdatabase/DatabaseManager.h"
     88 #include "weborigin/SecurityOrigin.h"
     89 #include "weborigin/SecurityPolicy.h"
     90 #include "wtf/TemporaryChange.h"
     91 #include "wtf/text/CString.h"
     92 #include "wtf/text/WTFString.h"
     93 
     94 namespace WebCore {
     95 
     96 using namespace HTMLNames;
     97 
     98 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
     99 
    100 bool isBackForwardLoadType(FrameLoadType type)
    101 {
    102     return type == FrameLoadTypeBackForward;
    103 }
    104 
    105 // This is not in the FrameLoader class to emphasize that it does not depend on
    106 // private FrameLoader data, and to avoid increasing the number of public functions
    107 // with access to private data.  Since only this .cpp file needs it, making it
    108 // non-member lets us exclude it from the header file, thus keeping core/loader/FrameLoader.h's
    109 // API simpler.
    110 //
    111 static bool isDocumentSandboxed(Frame* frame, SandboxFlags mask)
    112 {
    113     return frame->document() && frame->document()->isSandboxed(mask);
    114 }
    115 
    116 class FrameLoader::FrameProgressTracker {
    117 public:
    118     static PassOwnPtr<FrameProgressTracker> create(Frame* frame) { return adoptPtr(new FrameProgressTracker(frame)); }
    119     ~FrameProgressTracker()
    120     {
    121         ASSERT(!m_inProgress || m_frame->page());
    122         if (m_inProgress)
    123             m_frame->page()->progress()->progressCompleted(m_frame);
    124     }
    125 
    126     void progressStarted()
    127     {
    128         ASSERT(m_frame->page());
    129         if (!m_inProgress)
    130             m_frame->page()->progress()->progressStarted(m_frame);
    131         m_inProgress = true;
    132     }
    133 
    134     void progressCompleted()
    135     {
    136         ASSERT(m_inProgress);
    137         ASSERT(m_frame->page());
    138         m_inProgress = false;
    139         m_frame->page()->progress()->progressCompleted(m_frame);
    140     }
    141 
    142 private:
    143     FrameProgressTracker(Frame* frame)
    144         : m_frame(frame)
    145         , m_inProgress(false)
    146     {
    147     }
    148 
    149     Frame* m_frame;
    150     bool m_inProgress;
    151 };
    152 
    153 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
    154     : m_frame(frame)
    155     , m_client(client)
    156     , m_history(frame)
    157     , m_notifer(frame)
    158     , m_icon(adoptPtr(new IconController(frame)))
    159     , m_mixedContentChecker(frame)
    160     , m_state(FrameStateProvisional)
    161     , m_loadType(FrameLoadTypeStandard)
    162     , m_inStopAllLoaders(false)
    163     , m_pageDismissalEventBeingDispatched(NoDismissal)
    164     , m_isComplete(false)
    165     , m_containsPlugins(false)
    166     , m_needsClear(false)
    167     , m_checkTimer(this, &FrameLoader::checkTimerFired)
    168     , m_shouldCallCheckCompleted(false)
    169     , m_shouldCallCheckLoadComplete(false)
    170     , m_opener(0)
    171     , m_didAccessInitialDocument(false)
    172     , m_didAccessInitialDocumentTimer(this, &FrameLoader::didAccessInitialDocumentTimerFired)
    173     , m_suppressOpenerInNewFrame(false)
    174     , m_startingClientRedirect(false)
    175     , m_forcedSandboxFlags(SandboxNone)
    176     , m_hasAllowedNavigationViaBeforeUnloadConfirmationPanel(false)
    177 {
    178 }
    179 
    180 FrameLoader::~FrameLoader()
    181 {
    182     setOpener(0);
    183 
    184     HashSet<Frame*>::iterator end = m_openedFrames.end();
    185     for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it)
    186         (*it)->loader()->m_opener = 0;
    187 
    188     m_client->frameLoaderDestroyed();
    189 }
    190 
    191 void FrameLoader::init()
    192 {
    193     // This somewhat odd set of steps gives the frame an initial empty document.
    194     m_provisionalDocumentLoader = m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, emptyString())), SubstituteData());
    195     m_provisionalDocumentLoader->setFrame(m_frame);
    196     m_provisionalDocumentLoader->startLoadingMainResource();
    197     m_frame->document()->cancelParsing();
    198     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
    199     m_progressTracker = FrameProgressTracker::create(m_frame);
    200 }
    201 
    202 void FrameLoader::setDefersLoading(bool defers)
    203 {
    204     if (m_documentLoader)
    205         m_documentLoader->setDefersLoading(defers);
    206     if (m_provisionalDocumentLoader)
    207         m_provisionalDocumentLoader->setDefersLoading(defers);
    208     if (m_policyDocumentLoader)
    209         m_policyDocumentLoader->setDefersLoading(defers);
    210     history()->setDefersLoading(defers);
    211 
    212     if (!defers) {
    213         m_frame->navigationScheduler()->startTimer();
    214         startCheckCompleteTimer();
    215     }
    216 }
    217 
    218 void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission)
    219 {
    220     ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod);
    221 
    222     // FIXME: Find a good spot for these.
    223     ASSERT(submission->data());
    224     ASSERT(submission->state());
    225     ASSERT(!submission->state()->sourceDocument()->frame() || submission->state()->sourceDocument()->frame() == m_frame);
    226 
    227     if (!m_frame->page())
    228         return;
    229 
    230     if (submission->action().isEmpty())
    231         return;
    232 
    233     if (isDocumentSandboxed(m_frame, SandboxForms)) {
    234         // FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
    235         m_frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked form submission to '" + submission->action().elidedString() + "' because the form's frame is sandboxed and the 'allow-forms' permission is not set.");
    236         return;
    237     }
    238 
    239     if (protocolIsJavaScript(submission->action())) {
    240         if (!m_frame->document()->contentSecurityPolicy()->allowFormAction(KURL(submission->action())))
    241             return;
    242         m_frame->script()->executeScriptIfJavaScriptURL(submission->action());
    243         return;
    244     }
    245 
    246     Frame* targetFrame = findFrameForNavigation(submission->target(), submission->state()->sourceDocument());
    247     if (!targetFrame) {
    248         if (!DOMWindow::allowPopUp(m_frame) && !ScriptController::processingUserGesture())
    249             return;
    250 
    251         targetFrame = m_frame;
    252     } else
    253         submission->clearTarget();
    254 
    255     if (!targetFrame->page())
    256         return;
    257 
    258     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
    259 
    260     // We do not want to submit more than one form from the same page, nor do we want to submit a single
    261     // form more than once. This flag prevents these from happening; not sure how other browsers prevent this.
    262     // The flag is reset in each time we start handle a new mouse or key down event, and
    263     // also in setView since this part may get reused for a page from the back/forward cache.
    264     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
    265 
    266     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
    267     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
    268     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
    269 
    270     if (m_frame->tree()->isDescendantOf(targetFrame)) {
    271         if (m_submittedFormURL == submission->requestURL())
    272             return;
    273         m_submittedFormURL = submission->requestURL();
    274     }
    275 
    276     submission->setReferrer(outgoingReferrer());
    277     submission->setOrigin(outgoingOrigin());
    278 
    279     targetFrame->navigationScheduler()->scheduleFormSubmission(submission);
    280 }
    281 
    282 void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
    283 {
    284     if (m_frame->document() && m_frame->document()->parser())
    285         m_frame->document()->parser()->stopParsing();
    286 
    287     if (unloadEventPolicy != UnloadEventPolicyNone) {
    288         if (m_frame->document()) {
    289             if (m_frame->document()->unloadEventStillNeeded()) {
    290                 m_frame->document()->unloadEventStarted();
    291                 Element* currentFocusedElement = m_frame->document()->focusedElement();
    292                 if (currentFocusedElement && currentFocusedElement->hasTagName(inputTag))
    293                     toHTMLInputElement(currentFocusedElement)->endEditing();
    294                 if (m_pageDismissalEventBeingDispatched == NoDismissal) {
    295                     if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
    296                         m_pageDismissalEventBeingDispatched = PageHideDismissal;
    297                         m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, false), m_frame->document());
    298                     }
    299                     RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
    300                     // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
    301                     // while dispatching the event, so protect it to prevent writing the end
    302                     // time into freed memory.
    303                     RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
    304                     m_pageDismissalEventBeingDispatched = UnloadDismissal;
    305                     if (documentLoader && !documentLoader->timing()->unloadEventStart() && !documentLoader->timing()->unloadEventEnd()) {
    306                         DocumentLoadTiming* timing = documentLoader->timing();
    307                         ASSERT(timing->navigationStart());
    308                         timing->markUnloadEventStart();
    309                         m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->document());
    310                         timing->markUnloadEventEnd();
    311                     } else {
    312                         m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->document());
    313                     }
    314                 }
    315                 m_pageDismissalEventBeingDispatched = NoDismissal;
    316                 if (m_frame->document()) {
    317                     m_frame->document()->updateStyleIfNeeded();
    318                     m_frame->document()->unloadEventWasHandled();
    319                 }
    320             }
    321         }
    322 
    323         // Dispatching the unload event could have made m_frame->document() null.
    324         if (m_frame->document()) {
    325             // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
    326             bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
    327                 && m_frame->document()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
    328 
    329             if (!keepEventListeners)
    330                 m_frame->document()->removeAllEventListeners();
    331         }
    332     }
    333 
    334     m_isComplete = true; // to avoid calling completed() in finishedParsing()
    335 
    336     if (m_frame->document() && m_frame->document()->parsing()) {
    337         finishedParsing();
    338         m_frame->document()->setParsing(false);
    339     }
    340 
    341     if (Document* doc = m_frame->document()) {
    342         // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior.
    343         // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537
    344         doc->setReadyState(Document::Complete);
    345 
    346         // FIXME: Should the DatabaseManager watch for something like ActiveDOMObject::stop() rather than being special-cased here?
    347         DatabaseManager::manager().stopDatabases(doc, 0);
    348     }
    349 
    350     // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
    351     m_frame->navigationScheduler()->cancel();
    352 }
    353 
    354 void FrameLoader::stop()
    355 {
    356     // http://bugs.webkit.org/show_bug.cgi?id=10854
    357     // The frame's last ref may be removed and it will be deleted by checkCompleted().
    358     RefPtr<Frame> protector(m_frame);
    359 
    360     if (DocumentParser* parser = m_frame->document()->parser()) {
    361         parser->stopParsing();
    362         parser->finish();
    363     }
    364 }
    365 
    366 bool FrameLoader::closeURL()
    367 {
    368     history()->saveDocumentState();
    369 
    370     // Should only send the pagehide event here if the current document exists.
    371     Document* currentDocument = m_frame->document();
    372     stopLoading(currentDocument ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly);
    373 
    374     m_frame->editor()->clearUndoRedoOperations();
    375     return true;
    376 }
    377 
    378 void FrameLoader::didExplicitOpen()
    379 {
    380     m_isComplete = false;
    381 
    382     // Calling document.open counts as committing the first real document load.
    383     if (!m_stateMachine.committedFirstRealDocumentLoad())
    384         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
    385 
    386     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
    387     // from a subsequent window.document.open / window.document.write call.
    388     // Canceling redirection here works for all cases because document.open
    389     // implicitly precedes document.write.
    390     m_frame->navigationScheduler()->cancel();
    391 }
    392 
    393 void FrameLoader::cancelAndClear()
    394 {
    395     m_frame->navigationScheduler()->cancel();
    396 
    397     if (!m_isComplete)
    398         closeURL();
    399 
    400     clear(ClearScriptObjects | ClearWindowObject);
    401 }
    402 
    403 void FrameLoader::clear(ClearOptions options)
    404 {
    405     m_frame->editor()->clear();
    406 
    407     if (!m_needsClear)
    408         return;
    409     m_needsClear = false;
    410 
    411     m_frame->document()->cancelParsing();
    412     m_frame->document()->stopActiveDOMObjects();
    413     if (m_frame->document()->attached()) {
    414         m_frame->document()->prepareForDestruction();
    415         m_frame->document()->removeFocusedElementOfSubtree(m_frame->document());
    416     }
    417 
    418     // Do this after detaching the document so that the unload event works.
    419     if (options & ClearWindowProperties) {
    420         InspectorInstrumentation::frameWindowDiscarded(m_frame, m_frame->domWindow());
    421         m_frame->domWindow()->reset();
    422         m_frame->script()->clearWindowShell();
    423     }
    424 
    425     m_frame->selection()->prepareForDestruction();
    426     m_frame->eventHandler()->clear();
    427     if (m_frame->view())
    428         m_frame->view()->clear();
    429 
    430     if (options & ClearWindowObject) {
    431         // Do not drop the DOMWindow (and Document) before the ScriptController and view are cleared
    432         // as some destructors might still try to access the document.
    433         m_frame->setDOMWindow(0);
    434     }
    435 
    436     m_containsPlugins = false;
    437 
    438     if (options & ClearScriptObjects)
    439         m_frame->script()->clearScriptObjects();
    440 
    441     m_frame->script()->enableEval();
    442 
    443     m_frame->navigationScheduler()->clear();
    444 
    445     m_checkTimer.stop();
    446     m_shouldCallCheckCompleted = false;
    447     m_shouldCallCheckLoadComplete = false;
    448 
    449     if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad())
    450         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
    451 }
    452 
    453 void FrameLoader::receivedFirstData()
    454 {
    455     if (m_stateMachine.creatingInitialEmptyDocument())
    456         return;
    457 
    458     dispatchDidCommitLoad();
    459     dispatchDidClearWindowObjectsInAllWorlds();
    460 
    461     if (m_documentLoader) {
    462         StringWithDirection ptitle = m_documentLoader->title();
    463         // If we have a title let the WebView know about it.
    464         if (!ptitle.isNull())
    465             m_client->dispatchDidReceiveTitle(ptitle);
    466     }
    467 }
    468 
    469 void FrameLoader::setOutgoingReferrer(const KURL& url)
    470 {
    471     m_outgoingReferrer = url.strippedForUseAsReferrer();
    472 }
    473 
    474 void FrameLoader::didBeginDocument(bool dispatch)
    475 {
    476     m_needsClear = true;
    477     m_isComplete = false;
    478     m_frame->document()->setReadyState(Document::Loading);
    479 
    480     if (history()->currentItem() && m_loadType == FrameLoadTypeBackForward)
    481         m_frame->document()->statePopped(history()->currentItem()->stateObject());
    482 
    483     if (dispatch)
    484         dispatchDidClearWindowObjectsInAllWorlds();
    485 
    486     m_frame->document()->initContentSecurityPolicy(m_documentLoader ? ContentSecurityPolicyResponseHeaders(m_documentLoader->response()) : ContentSecurityPolicyResponseHeaders());
    487 
    488     Settings* settings = m_frame->document()->settings();
    489     if (settings) {
    490         m_frame->document()->fetcher()->setImagesEnabled(settings->areImagesEnabled());
    491         m_frame->document()->fetcher()->setAutoLoadImages(settings->loadsImagesAutomatically());
    492     }
    493 
    494     if (m_documentLoader) {
    495         String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
    496         if (!dnsPrefetchControl.isEmpty())
    497             m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
    498 
    499         String headerContentLanguage = m_documentLoader->response().httpHeaderField("Content-Language");
    500         if (!headerContentLanguage.isEmpty()) {
    501             size_t commaIndex = headerContentLanguage.find(',');
    502             headerContentLanguage.truncate(commaIndex); // notFound == -1 == don't truncate
    503             headerContentLanguage = headerContentLanguage.stripWhiteSpace(isHTMLSpace);
    504             if (!headerContentLanguage.isEmpty())
    505                 m_frame->document()->setContentLanguage(headerContentLanguage);
    506         }
    507     }
    508 
    509     history()->restoreDocumentState();
    510 }
    511 
    512 void FrameLoader::finishedParsing()
    513 {
    514     if (m_stateMachine.creatingInitialEmptyDocument())
    515         return;
    516 
    517     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
    518     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
    519     // Null-checking the FrameView indicates whether or not we're in the destructor.
    520     RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
    521 
    522     m_client->dispatchDidFinishDocumentLoad();
    523 
    524     checkCompleted();
    525 
    526     if (!m_frame->view())
    527         return; // We are being destroyed by something checkCompleted called.
    528 
    529     // Check if the scrollbars are really needed for the content.
    530     // If not, remove them, relayout, and repaint.
    531     m_frame->view()->restoreScrollbar();
    532     scrollToFragmentWithParentBoundary(m_frame->document()->url());
    533 }
    534 
    535 void FrameLoader::loadDone()
    536 {
    537     checkCompleted();
    538 }
    539 
    540 bool FrameLoader::allChildrenAreComplete() const
    541 {
    542     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
    543         if (!child->loader()->m_isComplete)
    544             return false;
    545     }
    546     return true;
    547 }
    548 
    549 bool FrameLoader::allAncestorsAreComplete() const
    550 {
    551     for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) {
    552         if (!ancestor->loader()->m_isComplete)
    553             return false;
    554     }
    555     return true;
    556 }
    557 
    558 void FrameLoader::checkCompleted()
    559 {
    560     RefPtr<Frame> protect(m_frame);
    561     m_shouldCallCheckCompleted = false;
    562 
    563     if (m_frame->view())
    564         m_frame->view()->handleLoadCompleted();
    565 
    566     // Have we completed before?
    567     if (m_isComplete)
    568         return;
    569 
    570     // Are we still parsing?
    571     if (m_frame->document()->parsing())
    572         return;
    573 
    574     // Still waiting for images/scripts?
    575     if (m_frame->document()->fetcher()->requestCount())
    576         return;
    577 
    578     // Still waiting for elements that don't go through a FrameLoader?
    579     if (m_frame->document()->isDelayingLoadEvent())
    580         return;
    581 
    582     // Any frame that hasn't completed yet?
    583     if (!allChildrenAreComplete())
    584         return;
    585 
    586     // OK, completed.
    587     m_isComplete = true;
    588     m_requestedHistoryItem = 0;
    589     m_frame->document()->setReadyState(Document::Complete);
    590     if (m_frame->document()->loadEventStillNeeded())
    591         m_frame->document()->implicitClose();
    592 
    593     m_frame->navigationScheduler()->startTimer();
    594 
    595     completed();
    596     if (m_frame->page())
    597         checkLoadComplete();
    598 
    599     if (m_frame->view())
    600         m_frame->view()->handleLoadCompleted();
    601 }
    602 
    603 void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
    604 {
    605     RefPtr<Frame> protect(m_frame);
    606 
    607     if (Page* page = m_frame->page()) {
    608         if (page->defersLoading())
    609             return;
    610     }
    611     if (m_shouldCallCheckCompleted)
    612         checkCompleted();
    613     if (m_shouldCallCheckLoadComplete)
    614         checkLoadComplete();
    615 }
    616 
    617 void FrameLoader::startCheckCompleteTimer()
    618 {
    619     if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
    620         return;
    621     if (m_checkTimer.isActive())
    622         return;
    623     m_checkTimer.startOneShot(0);
    624 }
    625 
    626 void FrameLoader::scheduleCheckCompleted()
    627 {
    628     m_shouldCallCheckCompleted = true;
    629     startCheckCompleteTimer();
    630 }
    631 
    632 void FrameLoader::scheduleCheckLoadComplete()
    633 {
    634     m_shouldCallCheckLoadComplete = true;
    635     startCheckCompleteTimer();
    636 }
    637 
    638 String FrameLoader::outgoingReferrer() const
    639 {
    640     // See http://www.whatwg.org/specs/web-apps/current-work/#fetching-resources
    641     // for why we walk the parent chain for srcdoc documents.
    642     Frame* frame = m_frame;
    643     while (frame->document()->isSrcdocDocument()) {
    644         frame = frame->tree()->parent();
    645         // Srcdoc documents cannot be top-level documents, by definition,
    646         // because they need to be contained in iframes with the srcdoc.
    647         ASSERT(frame);
    648     }
    649     return frame->loader()->m_outgoingReferrer;
    650 }
    651 
    652 String FrameLoader::outgoingOrigin() const
    653 {
    654     return m_frame->document()->securityOrigin()->toString();
    655 }
    656 
    657 bool FrameLoader::checkIfFormActionAllowedByCSP(const KURL& url) const
    658 {
    659     if (m_submittedFormURL.isEmpty())
    660         return true;
    661 
    662     return m_frame->document()->contentSecurityPolicy()->allowFormAction(url);
    663 }
    664 
    665 Frame* FrameLoader::opener()
    666 {
    667     return m_opener;
    668 }
    669 
    670 void FrameLoader::setOpener(Frame* opener)
    671 {
    672     if (m_opener && !opener)
    673         m_client->didDisownOpener();
    674 
    675     if (m_opener)
    676         m_opener->loader()->m_openedFrames.remove(m_frame);
    677     if (opener)
    678         opener->loader()->m_openedFrames.add(m_frame);
    679     m_opener = opener;
    680 
    681     if (m_frame->document())
    682         m_frame->document()->initSecurityContext();
    683 }
    684 
    685 // FIXME: This does not belong in FrameLoader!
    686 void FrameLoader::handleFallbackContent()
    687 {
    688     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
    689     if (!owner || !owner->hasTagName(objectTag))
    690         return;
    691     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
    692 }
    693 
    694 bool FrameLoader::allowPlugins(ReasonForCallingAllowPlugins reason)
    695 {
    696     Settings* settings = m_frame->settings();
    697     bool allowed = m_client->allowPlugins(settings && settings->arePluginsEnabled());
    698     if (!allowed && reason == AboutToInstantiatePlugin)
    699         m_client->didNotAllowPlugins();
    700     return allowed;
    701 }
    702 
    703 void FrameLoader::resetMultipleFormSubmissionProtection()
    704 {
    705     m_submittedFormURL = KURL();
    706 }
    707 
    708 void FrameLoader::updateForSameDocumentNavigation(const KURL& newURL, SameDocumentNavigationSource sameDocumentNavigationSource, PassRefPtr<SerializedScriptValue> data, const String& title, UpdateBackForwardListPolicy updateBackForwardList)
    709 {
    710     // Update the data source's request with the new URL to fake the URL change
    711     KURL oldURL = m_frame->document()->url();
    712     m_frame->document()->setURL(newURL);
    713     setOutgoingReferrer(newURL);
    714     documentLoader()->replaceRequestURLForSameDocumentNavigation(newURL);
    715 
    716     // updateBackForwardListForFragmentScroll() must happen after
    717     // replaceRequestURLForSameDocumentNavigation(), since we add based on
    718     // the current request.
    719     if (updateBackForwardList == UpdateBackForwardList)
    720         history()->updateBackForwardListForFragmentScroll();
    721 
    722     if (sameDocumentNavigationSource == SameDocumentNavigationDefault)
    723         history()->updateForSameDocumentNavigation();
    724     else if (sameDocumentNavigationSource == SameDocumentNavigationPushState)
    725         history()->pushState(data, title, newURL.string());
    726     else if (sameDocumentNavigationSource == SameDocumentNavigationReplaceState)
    727         history()->replaceState(data, title, newURL.string());
    728     else
    729         ASSERT_NOT_REACHED();
    730 
    731     // Generate start and stop notifications only when loader is completed so that we
    732     // don't fire them for fragment redirection that happens in window.onload handler.
    733     // See https://bugs.webkit.org/show_bug.cgi?id=31838
    734     if (m_frame->document()->loadEventFinished())
    735         m_client->postProgressStartedNotification();
    736 
    737     m_documentLoader->clearRedirectChain();
    738     if (m_documentLoader->isClientRedirect())
    739         m_documentLoader->appendRedirect(oldURL);
    740     m_documentLoader->appendRedirect(newURL);
    741 
    742     m_client->dispatchDidNavigateWithinPage();
    743 
    744     if (m_frame->document()->loadEventFinished())
    745         m_client->postProgressFinishedNotification();
    746 }
    747 
    748 void FrameLoader::loadInSameDocument(const KURL& url, PassRefPtr<SerializedScriptValue> stateObject, bool isNewNavigation)
    749 {
    750     // If we have a state object, we cannot also be a new navigation.
    751     ASSERT(!stateObject || (stateObject && !isNewNavigation));
    752 
    753     KURL oldURL = m_frame->document()->url();
    754     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
    755     bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier();
    756     if (hashChange) {
    757         m_frame->eventHandler()->stopAutoscrollTimer();
    758         m_frame->document()->enqueueHashchangeEvent(oldURL, url);
    759     }
    760     m_documentLoader->setIsClientRedirect((m_startingClientRedirect && !isNewNavigation) || !UserGestureIndicator::processingUserGesture());
    761     m_documentLoader->setReplacesCurrentHistoryItem(!isNewNavigation);
    762     UpdateBackForwardListPolicy updateBackForwardList = isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject ? UpdateBackForwardList : DoNotUpdateBackForwardList;
    763     updateForSameDocumentNavigation(url, SameDocumentNavigationDefault, 0, String(), updateBackForwardList);
    764 
    765     // It's important to model this as a load that starts and immediately finishes.
    766     // Otherwise, the parent frame may think we never finished loading.
    767     started();
    768 
    769     // We need to scroll to the fragment whether or not a hash change occurred, since
    770     // the user might have scrolled since the previous navigation.
    771     scrollToFragmentWithParentBoundary(url);
    772 
    773     m_isComplete = false;
    774     checkCompleted();
    775 
    776     m_frame->document()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue());
    777 }
    778 
    779 bool FrameLoader::isComplete() const
    780 {
    781     return m_isComplete;
    782 }
    783 
    784 void FrameLoader::completed()
    785 {
    786     RefPtr<Frame> protect(m_frame);
    787 
    788     for (Frame* descendant = m_frame->tree()->traverseNext(m_frame); descendant; descendant = descendant->tree()->traverseNext(m_frame))
    789         descendant->navigationScheduler()->startTimer();
    790 
    791     if (Frame* parent = m_frame->tree()->parent())
    792         parent->loader()->checkCompleted();
    793 
    794     if (m_frame->view())
    795         m_frame->view()->maintainScrollPositionAtAnchor(0);
    796 }
    797 
    798 void FrameLoader::started()
    799 {
    800     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
    801         frame->loader()->m_isComplete = false;
    802 }
    803 
    804 void FrameLoader::prepareForHistoryNavigation()
    805 {
    806     // If there is no currentItem, but we still want to engage in
    807     // history navigation we need to manufacture one, and update
    808     // the state machine of this frame to impersonate having
    809     // loaded it.
    810     RefPtr<HistoryItem> currentItem = history()->currentItem();
    811     if (!currentItem) {
    812         insertDummyHistoryItem();
    813 
    814         ASSERT(stateMachine()->isDisplayingInitialEmptyDocument());
    815         stateMachine()->advanceTo(FrameLoaderStateMachine::StartedFirstRealLoad);
    816         stateMachine()->advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
    817         stateMachine()->advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
    818     }
    819 }
    820 
    821 void FrameLoader::setReferrerForFrameRequest(ResourceRequest& request, ShouldSendReferrer shouldSendReferrer)
    822 {
    823     if (shouldSendReferrer == NeverSendReferrer) {
    824         request.clearHTTPReferrer();
    825         return;
    826     }
    827 
    828     String argsReferrer(request.httpReferrer());
    829     if (argsReferrer.isEmpty())
    830         argsReferrer = outgoingReferrer();
    831     String referrer = SecurityPolicy::generateReferrerHeader(m_frame->document()->referrerPolicy(), request.url(), argsReferrer);
    832 
    833     request.setHTTPReferrer(referrer);
    834     RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
    835     addHTTPOriginIfNeeded(request, referrerOrigin->toString());
    836 }
    837 
    838 FrameLoadType FrameLoader::determineFrameLoadType(const FrameLoadRequest& request)
    839 {
    840     if (m_frame->tree()->parent() && !m_stateMachine.startedFirstRealLoad())
    841         return FrameLoadTypeInitialInChildFrame;
    842     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
    843         return FrameLoadTypeReload;
    844     if (request.lockBackForwardList())
    845         return FrameLoadTypeRedirectWithLockedBackForwardList;
    846     if (!request.requester() && shouldTreatURLAsSameAsCurrent(request.resourceRequest().url()))
    847         return FrameLoadTypeSame;
    848     if (shouldTreatURLAsSameAsCurrent(request.substituteData().failingURL()) && m_loadType == FrameLoadTypeReload)
    849         return FrameLoadTypeReload;
    850     return FrameLoadTypeStandard;
    851 }
    852 
    853 bool FrameLoader::prepareRequestForThisFrame(FrameLoadRequest& request)
    854 {
    855     // If no SecurityOrigin was specified, skip security checks and assume the caller has fully initialized the FrameLoadRequest.
    856     if (!request.requester())
    857         return true;
    858 
    859     KURL url = request.resourceRequest().url();
    860     if (m_frame->script()->executeScriptIfJavaScriptURL(url))
    861         return false;
    862 
    863     if (!request.requester()->canDisplay(url)) {
    864         reportLocalLoadFailed(m_frame, url.elidedString());
    865         return false;
    866     }
    867 
    868     if (request.requester() && !request.formState() && request.frameName().isEmpty())
    869         request.setFrameName(m_frame->document()->baseTarget());
    870 
    871     // If the requesting SecurityOrigin is not this Frame's SecurityOrigin, the request was initiated by a different frame that should
    872     // have already set the referrer.
    873     if (request.requester() == m_frame->document()->securityOrigin())
    874         setReferrerForFrameRequest(request.resourceRequest(), request.shouldSendReferrer());
    875     return true;
    876 }
    877 
    878 static bool shouldOpenInNewWindow(Frame* targetFrame, const FrameLoadRequest& request, const NavigationAction& action)
    879 {
    880     if (!targetFrame && !request.frameName().isEmpty())
    881         return true;
    882     if (!request.formState())
    883         return false;
    884     NavigationPolicy navigationPolicy = NavigationPolicyCurrentTab;
    885     if (!action.specifiesNavigationPolicy(&navigationPolicy))
    886         return false;
    887     return navigationPolicy != NavigationPolicyCurrentTab;
    888 }
    889 
    890 void FrameLoader::load(const FrameLoadRequest& passedRequest)
    891 {
    892     ASSERT(!m_suppressOpenerInNewFrame);
    893     ASSERT(m_frame->document());
    894 
    895     // Protect frame from getting blown away inside dispatchBeforeLoadEvent in loadWithDocumentLoader.
    896     RefPtr<Frame> protect(m_frame);
    897 
    898     if (m_inStopAllLoaders)
    899         return;
    900 
    901     FrameLoadRequest request(passedRequest);
    902     if (!prepareRequestForThisFrame(request))
    903         return;
    904 
    905     // The search for a target frame is done earlier in the case of form submission.
    906     Frame* targetFrame = request.formState() ? 0 : findFrameForNavigation(request.frameName());
    907     if (targetFrame && targetFrame != m_frame) {
    908         request.setFrameName("_self");
    909         targetFrame->loader()->load(request);
    910         return;
    911     }
    912 
    913     FrameLoadType newLoadType = determineFrameLoadType(request);
    914     NavigationAction action(request.resourceRequest(), newLoadType, request.formState(), request.triggeringEvent());
    915     if (shouldOpenInNewWindow(targetFrame, request, action)) {
    916         TemporaryChange<bool> changeOpener(m_suppressOpenerInNewFrame, request.shouldSendReferrer() == NeverSendReferrer);
    917         checkNewWindowPolicyAndContinue(request.formState(), request.frameName(), action);
    918         return;
    919     }
    920 
    921     TemporaryChange<bool> changeClientRedirect(m_startingClientRedirect, request.clientRedirect());
    922     if (shouldPerformFragmentNavigation(request.formState(), request.resourceRequest().httpMethod(), newLoadType, request.resourceRequest().url())) {
    923         checkNavigationPolicyAndContinueFragmentScroll(action, newLoadType != FrameLoadTypeRedirectWithLockedBackForwardList);
    924         return;
    925     }
    926     bool sameURL = shouldTreatURLAsSameAsCurrent(request.resourceRequest().url());
    927     loadWithNavigationAction(request.resourceRequest(), action, newLoadType, request.formState(), request.substituteData());
    928     // Example of this case are sites that reload the same URL with a different cookie
    929     // driving the generated content, or a master frame with links that drive a target
    930     // frame, where the user has clicked on the same link repeatedly.
    931     if (sameURL && newLoadType != FrameLoadTypeReload && newLoadType != FrameLoadTypeReloadFromOrigin && request.resourceRequest().httpMethod() != "POST")
    932         m_loadType = FrameLoadTypeSame;
    933 }
    934 
    935 SubstituteData FrameLoader::defaultSubstituteDataForURL(const KURL& url)
    936 {
    937     if (!shouldTreatURLAsSrcdocDocument(url))
    938         return SubstituteData();
    939     String srcdoc = m_frame->ownerElement()->fastGetAttribute(srcdocAttr);
    940     ASSERT(!srcdoc.isNull());
    941     CString encodedSrcdoc = srcdoc.utf8();
    942     return SubstituteData(SharedBuffer::create(encodedSrcdoc.data(), encodedSrcdoc.length()), "text/html", "UTF-8", KURL());
    943 }
    944 
    945 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
    946 {
    947     ASSERT(!url.isEmpty());
    948     if (!frame)
    949         return;
    950 
    951     frame->document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url);
    952 }
    953 
    954 bool FrameLoader::willLoadMediaElementURL(KURL& url)
    955 {
    956     ResourceRequest request(url);
    957 
    958     unsigned long identifier;
    959     ResourceError error;
    960     requestFromDelegate(request, identifier, error);
    961     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), 0, -1, -1, error);
    962 
    963     url = request.url();
    964 
    965     return error.isNull();
    966 }
    967 
    968 void FrameLoader::reload(ReloadPolicy reloadPolicy, const KURL& overrideURL, const String& overrideEncoding)
    969 {
    970     DocumentLoader* documentLoader = activeDocumentLoader();
    971     if (!documentLoader)
    972         return;
    973 
    974     if (m_state == FrameStateProvisional)
    975         insertDummyHistoryItem();
    976     frame()->loader()->history()->saveDocumentAndScrollState();
    977 
    978     ResourceRequest request = documentLoader->request();
    979     // FIXME: We need to reset cache policy to prevent it from being incorrectly propagted to the reload.
    980     // Do we need to propagate anything other than the url?
    981     request.setCachePolicy(UseProtocolCachePolicy);
    982     if (!overrideURL.isEmpty())
    983         request.setURL(overrideURL);
    984     else if (!documentLoader->unreachableURL().isEmpty())
    985         request.setURL(documentLoader->unreachableURL());
    986 
    987     FrameLoadType type = reloadPolicy == EndToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload;
    988     NavigationAction action(request, type, request.httpMethod() == "POST");
    989     loadWithNavigationAction(request, action, type, 0, SubstituteData(), overrideEncoding);
    990 }
    991 
    992 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
    993 {
    994     if (m_pageDismissalEventBeingDispatched != NoDismissal)
    995         return;
    996 
    997     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
    998     if (m_inStopAllLoaders)
    999         return;
   1000 
   1001     // Calling stopLoading() on the provisional document loader can blow away
   1002     // the frame from underneath.
   1003     RefPtr<Frame> protect(m_frame);
   1004 
   1005     m_inStopAllLoaders = true;
   1006 
   1007     // If no new load is in progress, we should clear the provisional item from history
   1008     // before we call stopLoading.
   1009     if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
   1010         history()->setProvisionalItem(0);
   1011 
   1012     for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   1013         child->loader()->stopAllLoaders(clearProvisionalItemPolicy);
   1014     if (m_provisionalDocumentLoader)
   1015         m_provisionalDocumentLoader->stopLoading();
   1016     if (m_documentLoader)
   1017         m_documentLoader->stopLoading();
   1018 
   1019     if (m_provisionalDocumentLoader)
   1020         m_provisionalDocumentLoader->detachFromFrame();
   1021     m_provisionalDocumentLoader = 0;
   1022 
   1023     m_checkTimer.stop();
   1024 
   1025     m_inStopAllLoaders = false;
   1026 }
   1027 
   1028 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
   1029 {
   1030     // stopAllLoaders can detach the Frame, so protect it.
   1031     RefPtr<Frame> protect(m_frame);
   1032     stopAllLoaders();
   1033 
   1034     if (deferCheckLoadComplete)
   1035         scheduleCheckLoadComplete();
   1036     else if (m_frame->page())
   1037         checkLoadComplete();
   1038 }
   1039 
   1040 DocumentLoader* FrameLoader::activeDocumentLoader() const
   1041 {
   1042     if (m_state == FrameStateProvisional)
   1043         return m_provisionalDocumentLoader.get();
   1044     return m_documentLoader.get();
   1045 }
   1046 
   1047 void FrameLoader::didAccessInitialDocument()
   1048 {
   1049     // We only need to notify the client once, and only for the main frame.
   1050     if (isLoadingMainFrame() && !m_didAccessInitialDocument) {
   1051         m_didAccessInitialDocument = true;
   1052         // Notify asynchronously, since this is called within a JavaScript security check.
   1053         m_didAccessInitialDocumentTimer.startOneShot(0);
   1054     }
   1055 }
   1056 
   1057 void FrameLoader::didAccessInitialDocumentTimerFired(Timer<FrameLoader>*)
   1058 {
   1059     m_client->didAccessInitialDocument();
   1060 }
   1061 
   1062 void FrameLoader::notifyIfInitialDocumentAccessed()
   1063 {
   1064     if (m_didAccessInitialDocumentTimer.isActive()
   1065         && m_stateMachine.isDisplayingInitialEmptyDocument()) {
   1066         m_didAccessInitialDocumentTimer.stop();
   1067         didAccessInitialDocumentTimerFired(0);
   1068     }
   1069 }
   1070 
   1071 bool FrameLoader::isLoading() const
   1072 {
   1073     DocumentLoader* docLoader = activeDocumentLoader();
   1074     if (!docLoader)
   1075         return false;
   1076     return docLoader->isLoading();
   1077 }
   1078 
   1079 void FrameLoader::commitProvisionalLoad()
   1080 {
   1081     ASSERT(m_client->hasWebView());
   1082     ASSERT(m_state == FrameStateProvisional);
   1083     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
   1084     RefPtr<Frame> protect(m_frame);
   1085 
   1086     closeOldDataSources();
   1087 
   1088     // Check if the destination page is allowed to access the previous page's timing information.
   1089     if (m_frame->document()) {
   1090         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(pdl->request().url());
   1091         pdl->timing()->setHasSameOriginAsPreviousDocument(securityOrigin->canRequest(m_frame->document()->url()));
   1092     }
   1093 
   1094     clearAllowNavigationViaBeforeUnloadConfirmationPanel();
   1095 
   1096     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
   1097     // JavaScript. If the script initiates a new load, we need to abandon the current load,
   1098     // or the two will stomp each other.
   1099     if (m_documentLoader)
   1100         closeURL();
   1101     if (pdl != m_provisionalDocumentLoader)
   1102         return;
   1103 
   1104     // detachChildren() can trigger this frame's unload event, and therefore
   1105     // script can run and do just about anything. For example, an unload event that calls
   1106     // document.write("") on its parent frame can lead to a recursive detachChildren()
   1107     // invocation for this frame. Leave the loader that is being committed in a temporarily
   1108     // detached state, such that it can't be found and cancelled.
   1109     RefPtr<DocumentLoader> loaderBeingCommitted = m_provisionalDocumentLoader.release();
   1110     detachChildren();
   1111     if (m_documentLoader)
   1112         m_documentLoader->detachFromFrame();
   1113     m_documentLoader = loaderBeingCommitted;
   1114     m_state = FrameStateCommittedPage;
   1115 
   1116     if (isLoadingMainFrame())
   1117         m_frame->page()->chrome().client()->needTouchEvents(false);
   1118 
   1119     history()->updateForCommit();
   1120     m_client->transitionToCommittedForNewPage();
   1121 
   1122     if (!m_stateMachine.creatingInitialEmptyDocument() && !m_stateMachine.committedFirstRealDocumentLoad())
   1123         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
   1124 
   1125     // A redirect was scheduled before the first real document was committed.
   1126     // This can happen when one frame changes another frame's location.
   1127     if (m_frame->navigationScheduler()->redirectScheduledDuringLoad())
   1128         return;
   1129     m_frame->navigationScheduler()->cancel();
   1130     m_frame->editor()->clearLastEditCommand();
   1131 
   1132     // If we are still in the process of initializing an empty document then
   1133     // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
   1134     // since it may cause clients to attempt to render the frame.
   1135     if (!m_stateMachine.creatingInitialEmptyDocument()) {
   1136         DOMWindow* window = m_frame->domWindow();
   1137         window->setStatus(String());
   1138         window->setDefaultStatus(String());
   1139     }
   1140     started();
   1141 }
   1142 
   1143 void FrameLoader::closeOldDataSources()
   1144 {
   1145     // FIXME: Is it important for this traversal to be postorder instead of preorder?
   1146     // If so, add helpers for postorder traversal, and use them. If not, then lets not
   1147     // use a recursive algorithm here.
   1148     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   1149         child->loader()->closeOldDataSources();
   1150 
   1151     if (m_documentLoader)
   1152         m_client->dispatchWillClose();
   1153 }
   1154 
   1155 bool FrameLoader::isHostedByObjectElement() const
   1156 {
   1157     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
   1158     return owner && owner->hasTagName(objectTag);
   1159 }
   1160 
   1161 bool FrameLoader::isLoadingMainFrame() const
   1162 {
   1163     Page* page = m_frame->page();
   1164     return page && m_frame == page->mainFrame();
   1165 }
   1166 
   1167 bool FrameLoader::subframeIsLoading() const
   1168 {
   1169     // It's most likely that the last added frame is the last to load so we walk backwards.
   1170     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
   1171         FrameLoader* childLoader = child->loader();
   1172         DocumentLoader* documentLoader = childLoader->documentLoader();
   1173         if (documentLoader && documentLoader->isLoadingInAPISense())
   1174             return true;
   1175         documentLoader = childLoader->provisionalDocumentLoader();
   1176         if (documentLoader && documentLoader->isLoadingInAPISense())
   1177             return true;
   1178         documentLoader = childLoader->policyDocumentLoader();
   1179         if (documentLoader)
   1180             return true;
   1181     }
   1182     return false;
   1183 }
   1184 
   1185 FrameLoadType FrameLoader::loadType() const
   1186 {
   1187     return m_loadType;
   1188 }
   1189 
   1190 CachePolicy FrameLoader::subresourceCachePolicy() const
   1191 {
   1192     if (m_isComplete)
   1193         return CachePolicyVerify;
   1194 
   1195     if (m_loadType == FrameLoadTypeReloadFromOrigin)
   1196         return CachePolicyReload;
   1197 
   1198     if (Frame* parentFrame = m_frame->tree()->parent()) {
   1199         CachePolicy parentCachePolicy = parentFrame->loader()->subresourceCachePolicy();
   1200         if (parentCachePolicy != CachePolicyVerify)
   1201             return parentCachePolicy;
   1202     }
   1203 
   1204     if (m_loadType == FrameLoadTypeReload)
   1205         return CachePolicyRevalidate;
   1206 
   1207     const ResourceRequest& request(documentLoader()->request());
   1208 
   1209     if (request.cachePolicy() == ReturnCacheDataElseLoad)
   1210         return CachePolicyHistoryBuffer;
   1211 
   1212     return CachePolicyVerify;
   1213 }
   1214 
   1215 void FrameLoader::checkLoadCompleteForThisFrame()
   1216 {
   1217     ASSERT(m_client->hasWebView());
   1218     if (m_state != FrameStateCommittedPage)
   1219         return;
   1220 
   1221     if (!m_documentLoader || (m_documentLoader->isLoadingInAPISense() && !m_documentLoader->isStopping()))
   1222         return;
   1223 
   1224     m_state = FrameStateComplete;
   1225 
   1226     // FIXME: Is this subsequent work important if we already navigated away?
   1227     // Maybe there are bugs because of that, or extra work we can skip because
   1228     // the new page is ready.
   1229 
   1230     // If the user had a scroll point, scroll to it, overriding the anchor point if any.
   1231     if (m_frame->page()) {
   1232         if (isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin)
   1233             history()->restoreScrollPositionAndViewState();
   1234     }
   1235 
   1236     if (!m_stateMachine.committedFirstRealDocumentLoad())
   1237         return;
   1238 
   1239     m_progressTracker->progressCompleted();
   1240     if (Page* page = m_frame->page()) {
   1241         if (m_frame == page->mainFrame())
   1242             page->resetRelevantPaintedObjectCounter();
   1243     }
   1244 
   1245     const ResourceError& error = m_documentLoader->mainDocumentError();
   1246     if (!error.isNull())
   1247         m_client->dispatchDidFailLoad(error);
   1248     else
   1249         m_client->dispatchDidFinishLoad();
   1250     m_loadType = FrameLoadTypeStandard;
   1251 }
   1252 
   1253 void FrameLoader::didLayout(LayoutMilestones milestones)
   1254 {
   1255     m_client->dispatchDidLayout(milestones);
   1256 }
   1257 
   1258 void FrameLoader::didFirstLayout()
   1259 {
   1260     if (m_frame->page() && isBackForwardLoadType(m_loadType))
   1261         history()->restoreScrollPositionAndViewState();
   1262 }
   1263 
   1264 void FrameLoader::detachChildren()
   1265 {
   1266     typedef Vector<RefPtr<Frame> > FrameVector;
   1267     FrameVector childrenToDetach;
   1268     childrenToDetach.reserveCapacity(m_frame->tree()->childCount());
   1269     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling())
   1270         childrenToDetach.append(child);
   1271     FrameVector::iterator end = childrenToDetach.end();
   1272     for (FrameVector::iterator it = childrenToDetach.begin(); it != end; it++)
   1273         (*it)->loader()->detachFromParent();
   1274 }
   1275 
   1276 void FrameLoader::closeAndRemoveChild(Frame* child)
   1277 {
   1278     child->tree()->detachFromParent();
   1279 
   1280     child->setView(0);
   1281     if (child->ownerElement() && child->page())
   1282         child->page()->decrementSubframeCount();
   1283     child->willDetachPage();
   1284     child->detachFromPage();
   1285 
   1286     m_frame->tree()->removeChild(child);
   1287 }
   1288 
   1289 // Called every time a resource is completely loaded or an error is received.
   1290 void FrameLoader::checkLoadComplete()
   1291 {
   1292     ASSERT(m_client->hasWebView());
   1293 
   1294     m_shouldCallCheckLoadComplete = false;
   1295 
   1296     // FIXME: Always traversing the entire frame tree is a bit inefficient, but
   1297     // is currently needed in order to null out the previous history item for all frames.
   1298     if (Page* page = m_frame->page()) {
   1299         Vector<RefPtr<Frame>, 10> frames;
   1300         for (RefPtr<Frame> frame = page->mainFrame(); frame; frame = frame->tree()->traverseNext())
   1301             frames.append(frame);
   1302         // To process children before their parents, iterate the vector backwards.
   1303         for (size_t i = frames.size(); i; --i)
   1304             frames[i - 1]->loader()->checkLoadCompleteForThisFrame();
   1305     }
   1306 }
   1307 
   1308 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
   1309 {
   1310     if (!recurse)
   1311         return m_frame->document()->fetcher()->requestCount();
   1312 
   1313     int count = 0;
   1314     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
   1315         count += frame->document()->fetcher()->requestCount();
   1316     return count;
   1317 }
   1318 
   1319 String FrameLoader::userAgent(const KURL& url) const
   1320 {
   1321     String userAgent = m_client->userAgent(url);
   1322     InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent);
   1323     return userAgent;
   1324 }
   1325 
   1326 void FrameLoader::frameDetached()
   1327 {
   1328     // stopAllLoaders can detach the Frame, so protect it.
   1329     RefPtr<Frame> protect(m_frame);
   1330     stopAllLoaders();
   1331     m_frame->document()->stopActiveDOMObjects();
   1332     detachFromParent();
   1333 }
   1334 
   1335 void FrameLoader::detachFromParent()
   1336 {
   1337     // stopAllLoaders can detach the Frame, so protect it.
   1338     RefPtr<Frame> protect(m_frame);
   1339 
   1340     closeURL();
   1341     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
   1342     detachChildren();
   1343     // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren()
   1344     // will trigger the unload event handlers of any child frames, and those event
   1345     // handlers might start a new subresource load in this frame.
   1346     stopAllLoaders();
   1347 
   1348     InspectorInstrumentation::frameDetachedFromParent(m_frame);
   1349 
   1350     if (m_documentLoader)
   1351         m_documentLoader->detachFromFrame();
   1352     m_documentLoader = 0;
   1353     m_client->detachedFromParent();
   1354 
   1355     m_progressTracker.clear();
   1356 
   1357     if (Frame* parent = m_frame->tree()->parent()) {
   1358         parent->loader()->closeAndRemoveChild(m_frame);
   1359         parent->loader()->scheduleCheckCompleted();
   1360     } else {
   1361         m_frame->setView(0);
   1362         m_frame->willDetachPage();
   1363         m_frame->detachFromPage();
   1364     }
   1365 }
   1366 
   1367 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request)
   1368 {
   1369     bool isMainResource = (request.targetType() == ResourceRequest::TargetIsMainFrame) || (request.targetType() == ResourceRequest::TargetIsSubframe);
   1370 
   1371     if (isMainResource && isLoadingMainFrame())
   1372         request.setFirstPartyForCookies(request.url());
   1373     else
   1374         request.setFirstPartyForCookies(m_frame->document()->firstPartyForCookies());
   1375 
   1376     // The remaining modifications are only necessary for HTTP and HTTPS.
   1377     if (!request.url().isEmpty() && !request.url().protocolIsInHTTPFamily())
   1378         return;
   1379 
   1380     applyUserAgent(request);
   1381 
   1382     if (request.cachePolicy() == ReloadIgnoringCacheData) {
   1383         if (m_loadType == FrameLoadTypeReload)
   1384             request.setHTTPHeaderField("Cache-Control", "max-age=0");
   1385         else if (m_loadType == FrameLoadTypeReloadFromOrigin) {
   1386             request.setHTTPHeaderField("Cache-Control", "no-cache");
   1387             request.setHTTPHeaderField("Pragma", "no-cache");
   1388         }
   1389     }
   1390 
   1391     if (isMainResource)
   1392         request.setHTTPAccept(defaultAcceptHeader);
   1393 
   1394     // Make sure we send the Origin header.
   1395     addHTTPOriginIfNeeded(request, String());
   1396 }
   1397 
   1398 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, const String& origin)
   1399 {
   1400     if (!request.httpOrigin().isEmpty())
   1401         return;  // Request already has an Origin header.
   1402 
   1403     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
   1404     // For example, if an intranet page has a hyperlink to an external web
   1405     // site, we don't want to include the Origin of the request because it
   1406     // will leak the internal host name. Similar privacy concerns have lead
   1407     // to the widespread suppression of the Referer header at the network
   1408     // layer.
   1409     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
   1410         return;
   1411 
   1412     // For non-GET and non-HEAD methods, always send an Origin header so the
   1413     // server knows we support this feature.
   1414 
   1415     if (origin.isEmpty()) {
   1416         // If we don't know what origin header to attach, we attach the value
   1417         // for an empty origin.
   1418         request.setHTTPOrigin(SecurityOrigin::createUnique()->toString());
   1419         return;
   1420     }
   1421 
   1422     request.setHTTPOrigin(origin);
   1423 }
   1424 
   1425 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data)
   1426 {
   1427     ASSERT(m_frame->document());
   1428     String referrer = SecurityPolicy::generateReferrerHeader(m_frame->document()->referrerPolicy(), request.url(), outgoingReferrer());
   1429 
   1430     ResourceRequest initialRequest = request;
   1431     initialRequest.setTimeoutInterval(10);
   1432 
   1433     if (!referrer.isEmpty())
   1434         initialRequest.setHTTPReferrer(referrer);
   1435     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
   1436 
   1437     addExtraFieldsToRequest(initialRequest);
   1438 
   1439     unsigned long identifier = 0;
   1440     ResourceRequest newRequest(initialRequest);
   1441     requestFromDelegate(newRequest, identifier, error);
   1442 
   1443     if (error.isNull()) {
   1444         ASSERT(!newRequest.isNull());
   1445         documentLoader()->applicationCacheHost()->willStartLoadingSynchronously(newRequest);
   1446         ResourceLoader::loadResourceSynchronously(newRequest, storedCredentials, error, response, data);
   1447     }
   1448     int encodedDataLength = response.resourceLoadInfo() ? static_cast<int>(response.resourceLoadInfo()->encodedDataLength) : -1;
   1449     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.data(), data.size(), encodedDataLength, error);
   1450     return identifier;
   1451 }
   1452 
   1453 const ResourceRequest& FrameLoader::originalRequest() const
   1454 {
   1455     return activeDocumentLoader()->originalRequestCopy();
   1456 }
   1457 
   1458 void FrameLoader::receivedMainResourceError(const ResourceError& error)
   1459 {
   1460     // Retain because the stop may release the last reference to it.
   1461     RefPtr<Frame> protect(m_frame);
   1462 
   1463     RefPtr<DocumentLoader> loader = activeDocumentLoader();
   1464     // FIXME: Don't want to do this if an entirely new load is going, so should check
   1465     // that both data sources on the frame are either this or nil.
   1466     stop();
   1467 
   1468     // FIXME: We really ought to be able to just check for isCancellation() here, but there are some
   1469     // ResourceErrors that setIsCancellation() but aren't created by ResourceError::cancelledError().
   1470     ResourceError c(ResourceError::cancelledError(KURL()));
   1471     if (error.errorCode() != c.errorCode() || error.domain() != c.domain())
   1472         handleFallbackContent();
   1473 
   1474     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
   1475         if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
   1476             m_submittedFormURL = KURL();
   1477 
   1478         m_client->dispatchDidFailProvisionalLoad(error);
   1479         if (loader != m_provisionalDocumentLoader)
   1480             return;
   1481         m_provisionalDocumentLoader->detachFromFrame();
   1482         m_provisionalDocumentLoader = 0;
   1483         m_progressTracker->progressCompleted();
   1484         m_state = FrameStateComplete;
   1485 
   1486         // Reset the back forward list to the last committed history item at the top level.
   1487         RefPtr<HistoryItem> item = m_frame->page()->mainFrame()->loader()->history()->currentItem();
   1488         if (isBackForwardLoadType(loadType()) && !history()->provisionalItem() && item)
   1489             m_frame->page()->backForward()->setCurrentItem(item.get());
   1490     }
   1491 
   1492     checkCompleted();
   1493     if (m_frame->page())
   1494         checkLoadComplete();
   1495 }
   1496 
   1497 void FrameLoader::checkNavigationPolicyAndContinueFragmentScroll(const NavigationAction& action, bool isNewNavigation)
   1498 {
   1499     m_documentLoader->setTriggeringAction(action);
   1500 
   1501     const ResourceRequest& request = action.resourceRequest();
   1502     if (!m_documentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckFragment))
   1503         return;
   1504 
   1505     // If we have a provisional request for a different document, a fragment scroll should cancel it.
   1506     if (m_provisionalDocumentLoader && !equalIgnoringFragmentIdentifier(m_provisionalDocumentLoader->request().url(), request.url())) {
   1507         m_provisionalDocumentLoader->stopLoading();
   1508         if (m_provisionalDocumentLoader)
   1509             m_provisionalDocumentLoader->detachFromFrame();
   1510         m_provisionalDocumentLoader = 0;
   1511     }
   1512     loadInSameDocument(request.url(), 0, isNewNavigation);
   1513 }
   1514 
   1515 bool FrameLoader::shouldPerformFragmentNavigation(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url)
   1516 {
   1517     ASSERT(loadType != FrameLoadTypeBackForward);
   1518     ASSERT(loadType != FrameLoadTypeReloadFromOrigin);
   1519     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
   1520     // currently displaying a frameset, or if the URL does not have a fragment.
   1521     return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET"))
   1522         && loadType != FrameLoadTypeReload
   1523         && loadType != FrameLoadTypeSame
   1524         && url.hasFragmentIdentifier()
   1525         && equalIgnoringFragmentIdentifier(m_frame->document()->url(), url)
   1526         // We don't want to just scroll if a link from within a
   1527         // frameset is trying to reload the frameset into _top.
   1528         && !m_frame->document()->isFrameSet();
   1529 }
   1530 
   1531 void FrameLoader::scrollToFragmentWithParentBoundary(const KURL& url)
   1532 {
   1533     FrameView* view = m_frame->view();
   1534     if (!view)
   1535         return;
   1536 
   1537     // Leaking scroll position to a cross-origin ancestor would permit the so-called "framesniffing" attack.
   1538     RefPtr<Frame> boundaryFrame(url.hasFragmentIdentifier() ? m_frame->document()->findUnsafeParentScrollPropagationBoundary() : 0);
   1539 
   1540     if (boundaryFrame)
   1541         boundaryFrame->view()->setSafeToPropagateScrollToParent(false);
   1542 
   1543     view->scrollToFragment(url);
   1544 
   1545     if (boundaryFrame)
   1546         boundaryFrame->view()->setSafeToPropagateScrollToParent(true);
   1547 }
   1548 
   1549 bool FrameLoader::shouldClose()
   1550 {
   1551     Page* page = m_frame->page();
   1552     if (!page || !page->chrome().canRunBeforeUnloadConfirmPanel())
   1553         return true;
   1554 
   1555     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
   1556     Vector<RefPtr<Frame> > targetFrames;
   1557     targetFrames.append(m_frame);
   1558     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame))
   1559         targetFrames.append(child);
   1560 
   1561     bool shouldClose = false;
   1562     {
   1563         NavigationDisablerForBeforeUnload navigationDisabler;
   1564         size_t i;
   1565 
   1566         for (i = 0; i < targetFrames.size(); i++) {
   1567             if (!targetFrames[i]->tree()->isDescendantOf(m_frame))
   1568                 continue;
   1569             if (!targetFrames[i]->loader()->fireBeforeUnloadEvent(page->chrome(), this))
   1570                 break;
   1571         }
   1572 
   1573         if (i == targetFrames.size())
   1574             shouldClose = true;
   1575     }
   1576 
   1577     if (!shouldClose)
   1578         m_submittedFormURL = KURL();
   1579 
   1580     return shouldClose;
   1581 }
   1582 
   1583 bool FrameLoader::fireBeforeUnloadEvent(Chrome& chrome, FrameLoader* navigatingFrameLoader)
   1584 {
   1585     DOMWindow* domWindow = m_frame->domWindow();
   1586     if (!domWindow)
   1587         return true;
   1588 
   1589     RefPtr<Document> document = m_frame->document();
   1590     if (!document->body())
   1591         return true;
   1592 
   1593     RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
   1594     m_pageDismissalEventBeingDispatched = BeforeUnloadDismissal;
   1595     domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document());
   1596     m_pageDismissalEventBeingDispatched = NoDismissal;
   1597 
   1598     if (!beforeUnloadEvent->defaultPrevented())
   1599         document->defaultEventHandler(beforeUnloadEvent.get());
   1600     if (beforeUnloadEvent->result().isNull())
   1601         return true;
   1602 
   1603     if (navigatingFrameLoader->hasAllowedNavigationViaBeforeUnloadConfirmationPanel()) {
   1604         m_frame->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Blocked attempt to show multiple 'beforeunload' confirmation panels for a single navigation.");
   1605         return true;
   1606     }
   1607 
   1608     String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->result());
   1609     if (chrome.runBeforeUnloadConfirmPanel(text, m_frame)) {
   1610         navigatingFrameLoader->didAllowNavigationViaBeforeUnloadConfirmationPanel();
   1611         return true;
   1612     }
   1613     return false;
   1614 }
   1615 
   1616 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState, const SubstituteData& substituteData, const String& overrideEncoding)
   1617 {
   1618     ASSERT(m_client->hasWebView());
   1619     if (m_pageDismissalEventBeingDispatched != NoDismissal)
   1620         return;
   1621 
   1622     // We skip dispatching the beforeload event on the frame owner if we've already committed a real
   1623     // document load because the event would leak subsequent activity by the frame which the parent
   1624     // frame isn't supposed to learn. For example, if the child frame navigated to  a new URL, the
   1625     // parent frame shouldn't learn the URL.
   1626     if (!m_stateMachine.committedFirstRealDocumentLoad() && m_frame->ownerElement() && !m_frame->ownerElement()->dispatchBeforeLoadEvent(request.url().string()))
   1627         return;
   1628 
   1629     if (!m_stateMachine.startedFirstRealLoad())
   1630         m_stateMachine.advanceTo(FrameLoaderStateMachine::StartedFirstRealLoad);
   1631 
   1632     m_policyDocumentLoader = m_client->createDocumentLoader(request, substituteData.isValid() ? substituteData : defaultSubstituteDataForURL(request.url()));
   1633     m_policyDocumentLoader->setFrame(m_frame);
   1634     m_policyDocumentLoader->setTriggeringAction(action);
   1635     m_policyDocumentLoader->setReplacesCurrentHistoryItem(type == FrameLoadTypeRedirectWithLockedBackForwardList);
   1636     m_policyDocumentLoader->setIsClientRedirect(m_startingClientRedirect);
   1637 
   1638     if (Frame* parent = m_frame->tree()->parent())
   1639         m_policyDocumentLoader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
   1640     else if (!overrideEncoding.isEmpty())
   1641         m_policyDocumentLoader->setOverrideEncoding(overrideEncoding);
   1642     else if (m_documentLoader)
   1643         m_policyDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   1644 
   1645     // stopAllLoaders can detach the Frame, so protect it.
   1646     RefPtr<Frame> protect(m_frame);
   1647     if (!m_policyDocumentLoader->shouldContinueForNavigationPolicy(request, DocumentLoader::PolicyCheckStandard) || !shouldClose()) {
   1648         m_policyDocumentLoader->detachFromFrame();
   1649         m_policyDocumentLoader = 0;
   1650         return;
   1651     }
   1652 
   1653     // A new navigation is in progress, so don't clear the history's provisional item.
   1654     stopAllLoaders(ShouldNotClearProvisionalItem);
   1655 
   1656     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
   1657     // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
   1658     if (!m_frame->page())
   1659         return;
   1660 
   1661     if (isLoadingMainFrame())
   1662         m_frame->page()->inspectorController()->resume();
   1663     m_frame->navigationScheduler()->cancel();
   1664 
   1665     m_provisionalDocumentLoader = m_policyDocumentLoader.release();
   1666     m_loadType = type;
   1667     m_state = FrameStateProvisional;
   1668 
   1669     if (formState)
   1670         m_client->dispatchWillSubmitForm(formState);
   1671 
   1672     m_progressTracker->progressStarted();
   1673     if (m_provisionalDocumentLoader->isClientRedirect())
   1674         m_provisionalDocumentLoader->appendRedirect(m_frame->document()->url());
   1675     m_provisionalDocumentLoader->appendRedirect(m_provisionalDocumentLoader->request().url());
   1676     m_client->dispatchDidStartProvisionalLoad();
   1677     ASSERT(m_provisionalDocumentLoader);
   1678     m_provisionalDocumentLoader->startLoadingMainResource();
   1679 }
   1680 
   1681 void FrameLoader::checkNewWindowPolicyAndContinue(PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action)
   1682 {
   1683     if (m_pageDismissalEventBeingDispatched != NoDismissal)
   1684         return;
   1685 
   1686     if (m_frame->document() && m_frame->document()->isSandboxed(SandboxPopups))
   1687         return;
   1688 
   1689     if (!DOMWindow::allowPopUp(m_frame))
   1690         return;
   1691 
   1692     NavigationPolicy navigationPolicy = NavigationPolicyNewForegroundTab;
   1693     action.specifiesNavigationPolicy(&navigationPolicy);
   1694 
   1695     if (navigationPolicy == NavigationPolicyDownload) {
   1696         m_client->loadURLExternally(action.resourceRequest(), navigationPolicy);
   1697         return;
   1698     }
   1699 
   1700     RefPtr<Frame> frame = m_frame;
   1701     RefPtr<Frame> mainFrame = m_frame;
   1702 
   1703     if (!m_frame->settings() || m_frame->settings()->supportsMultipleWindows()) {
   1704         struct WindowFeatures features;
   1705         Page* newPage = m_frame->page()->chrome().client()->createWindow(m_frame, FrameLoadRequest(m_frame->document()->securityOrigin()),
   1706             features, action, navigationPolicy);
   1707 
   1708         // createWindow can return null (e.g., popup blocker denies the window).
   1709         if (!newPage)
   1710             return;
   1711         mainFrame = newPage->mainFrame();
   1712     }
   1713 
   1714     if (frameName != "_blank")
   1715         mainFrame->tree()->setName(frameName);
   1716 
   1717     mainFrame->page()->setOpenedByDOM();
   1718     mainFrame->page()->chrome().show(navigationPolicy);
   1719     if (!m_suppressOpenerInNewFrame) {
   1720         mainFrame->loader()->setOpener(frame.get());
   1721         mainFrame->document()->setReferrerPolicy(frame->document()->referrerPolicy());
   1722     }
   1723 
   1724     // FIXME: We can't just send our NavigationAction to the new FrameLoader's loadWithNavigationAction(), we need to
   1725     // create a new one with a default NavigationType and no triggering event. We should figure out why.
   1726     mainFrame->loader()->loadWithNavigationAction(action.resourceRequest(), NavigationAction(action.resourceRequest()), FrameLoadTypeStandard, formState, SubstituteData());
   1727 }
   1728 
   1729 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
   1730 {
   1731     ASSERT(!request.isNull());
   1732 
   1733     identifier = 0;
   1734     if (Page* page = m_frame->page())
   1735         identifier = createUniqueIdentifier();
   1736 
   1737     ResourceRequest newRequest(request);
   1738     notifier()->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
   1739 
   1740     if (newRequest.isNull())
   1741         error = ResourceError::cancelledError(request.url());
   1742     else
   1743         error = ResourceError();
   1744 
   1745     request = newRequest;
   1746 }
   1747 
   1748 void FrameLoader::loadedResourceFromMemoryCache(Resource* resource)
   1749 {
   1750     Page* page = m_frame->page();
   1751     if (!page)
   1752         return;
   1753 
   1754     if (!resource->shouldSendResourceLoadCallbacks())
   1755         return;
   1756 
   1757     // Main resource delegate messages are synthesized in MainResourceLoader, so we must not send them here.
   1758     if (resource->type() == Resource::MainResource)
   1759         return;
   1760 
   1761     ResourceRequest request(resource->url());
   1762     m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
   1763 
   1764     unsigned long identifier;
   1765     ResourceError error;
   1766     requestFromDelegate(request, identifier, error);
   1767     InspectorInstrumentation::markResourceAsCached(page, identifier);
   1768     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), 0, resource->encodedSize(), 0, error);
   1769 }
   1770 
   1771 void FrameLoader::applyUserAgent(ResourceRequest& request)
   1772 {
   1773     String userAgent = this->userAgent(request.url());
   1774     ASSERT(!userAgent.isNull());
   1775     request.setHTTPUserAgent(userAgent);
   1776 }
   1777 
   1778 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url, unsigned long requestIdentifier)
   1779 {
   1780     UseCounter::count(m_frame->document(), UseCounter::XFrameOptions);
   1781 
   1782     Frame* topFrame = m_frame->tree()->top();
   1783     if (m_frame == topFrame)
   1784         return false;
   1785 
   1786     XFrameOptionsDisposition disposition = parseXFrameOptionsHeader(content);
   1787 
   1788     switch (disposition) {
   1789     case XFrameOptionsSameOrigin: {
   1790         UseCounter::count(m_frame->document(), UseCounter::XFrameOptionsSameOrigin);
   1791         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
   1792         if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin()))
   1793             return true;
   1794         for (Frame* frame = m_frame->tree()->parent(); frame; frame = frame->tree()->parent()) {
   1795             if (!origin->isSameSchemeHostPort(frame->document()->securityOrigin())) {
   1796                 UseCounter::count(m_frame->document(), UseCounter::XFrameOptionsSameOriginWithBadAncestorChain);
   1797                 break;
   1798             }
   1799         }
   1800         return false;
   1801     }
   1802     case XFrameOptionsDeny:
   1803         return true;
   1804     case XFrameOptionsAllowAll:
   1805         return false;
   1806     case XFrameOptionsConflict:
   1807         m_frame->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Multiple 'X-Frame-Options' headers with conflicting values ('" + content + "') encountered when loading '" + url.elidedString() + "'. Falling back to 'DENY'.", requestIdentifier);
   1808         return true;
   1809     case XFrameOptionsInvalid:
   1810         m_frame->document()->addConsoleMessage(JSMessageSource, ErrorMessageLevel, "Invalid 'X-Frame-Options' header encountered when loading '" + url.elidedString() + "': '" + content + "' is not a recognized directive. The header will be ignored.", requestIdentifier);
   1811         return false;
   1812     default:
   1813         ASSERT_NOT_REACHED();
   1814         return false;
   1815     }
   1816 }
   1817 
   1818 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
   1819 {
   1820     if (!history()->currentItem())
   1821         return false;
   1822     return url == history()->currentItem()->url() || url == history()->currentItem()->originalURL();
   1823 }
   1824 
   1825 bool FrameLoader::shouldTreatURLAsSrcdocDocument(const KURL& url) const
   1826 {
   1827     if (!equalIgnoringCase(url.string(), "about:srcdoc"))
   1828         return false;
   1829     HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement();
   1830     if (!ownerElement)
   1831         return false;
   1832     if (!ownerElement->hasTagName(iframeTag))
   1833         return false;
   1834     return ownerElement->fastHasAttribute(srcdocAttr);
   1835 }
   1836 
   1837 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name, Document* activeDocument)
   1838 {
   1839     Frame* frame = m_frame->tree()->find(name);
   1840 
   1841     // From http://www.whatwg.org/specs/web-apps/current-work/#seamlessLinks:
   1842     //
   1843     // If the source browsing context is the same as the browsing context
   1844     // being navigated, and this browsing context has its seamless browsing
   1845     // context flag set, and the browsing context being navigated was not
   1846     // chosen using an explicit self-navigation override, then find the
   1847     // nearest ancestor browsing context that does not have its seamless
   1848     // browsing context flag set, and continue these steps as if that
   1849     // browsing context was the one that was going to be navigated instead.
   1850     if (frame == m_frame && name != "_self" && m_frame->document()->shouldDisplaySeamlesslyWithParent()) {
   1851         for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) {
   1852             if (!ancestor->document()->shouldDisplaySeamlesslyWithParent()) {
   1853                 frame = ancestor;
   1854                 break;
   1855             }
   1856         }
   1857         ASSERT(frame != m_frame);
   1858     }
   1859 
   1860     if (activeDocument) {
   1861         if (!activeDocument->canNavigate(frame))
   1862             return 0;
   1863     } else {
   1864         // FIXME: Eventually all callers should supply the actual activeDocument
   1865         // so we can call canNavigate with the right document.
   1866         if (!m_frame->document()->canNavigate(frame))
   1867             return 0;
   1868     }
   1869 
   1870     return frame;
   1871 }
   1872 
   1873 void FrameLoader::loadSameDocumentItem(HistoryItem* item)
   1874 {
   1875     ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentSequenceNumber());
   1876 
   1877     // Save user view state to the current history item here since we don't do a normal load.
   1878     // FIXME: Does form state need to be saved here too?
   1879     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
   1880     if (FrameView* view = m_frame->view())
   1881         view->setWasScrolledByUser(false);
   1882 
   1883     history()->setCurrentItem(item);
   1884 
   1885     // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
   1886     loadInSameDocument(item->url(), item->stateObject(), false);
   1887 
   1888     // Restore user view state from the current history item here since we don't do a normal load.
   1889     history()->restoreScrollPositionAndViewState();
   1890 }
   1891 
   1892 // FIXME: This function should really be split into a couple pieces, some of
   1893 // which should be methods of HistoryController and some of which should be
   1894 // methods of FrameLoader.
   1895 void FrameLoader::loadDifferentDocumentItem(HistoryItem* item)
   1896 {
   1897     // Remember this item so we can traverse any child items as child frames load
   1898     history()->setProvisionalItem(item);
   1899 
   1900     RefPtr<FormData> formData = item->formData();
   1901     ResourceRequest request(item->url());
   1902     request.setHTTPReferrer(item->referrer());
   1903     if (formData) {
   1904         request.setHTTPMethod("POST");
   1905         request.setHTTPBody(formData);
   1906         request.setHTTPContentType(item->formContentType());
   1907         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer());
   1908         addHTTPOriginIfNeeded(request, securityOrigin->toString());
   1909     }
   1910 
   1911     loadWithNavigationAction(request, NavigationAction(request, FrameLoadTypeBackForward, formData), FrameLoadTypeBackForward, 0, SubstituteData());
   1912 }
   1913 
   1914 void FrameLoader::loadHistoryItem(HistoryItem* item)
   1915 {
   1916     m_requestedHistoryItem = item;
   1917     HistoryItem* currentItem = history()->currentItem();
   1918     bool sameDocumentNavigation = currentItem && item->shouldDoSameDocumentNavigationTo(currentItem);
   1919 
   1920     if (sameDocumentNavigation)
   1921         loadSameDocumentItem(item);
   1922     else
   1923         loadDifferentDocumentItem(item);
   1924 }
   1925 
   1926 void FrameLoader::insertDummyHistoryItem()
   1927 {
   1928     RefPtr<HistoryItem> currentItem = HistoryItem::create();
   1929     history()->setCurrentItem(currentItem.get());
   1930     frame()->page()->backForward()->setCurrentItem(currentItem.get());
   1931 }
   1932 
   1933 void FrameLoader::setTitle(const StringWithDirection& title)
   1934 {
   1935     documentLoader()->setTitle(title);
   1936 }
   1937 
   1938 String FrameLoader::referrer() const
   1939 {
   1940     return m_documentLoader ? m_documentLoader->request().httpReferrer() : "";
   1941 }
   1942 
   1943 void FrameLoader::dispatchDocumentElementAvailable()
   1944 {
   1945     m_client->documentElementAvailable();
   1946 }
   1947 
   1948 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
   1949 {
   1950     if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript))
   1951         return;
   1952 
   1953     Vector<RefPtr<DOMWrapperWorld> > worlds;
   1954     DOMWrapperWorld::getAllWorlds(worlds);
   1955     for (size_t i = 0; i < worlds.size(); ++i)
   1956         dispatchDidClearWindowObjectInWorld(worlds[i].get());
   1957 }
   1958 
   1959 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
   1960 {
   1961     if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript) || !m_frame->script()->existingWindowShell(world))
   1962         return;
   1963 
   1964     m_client->dispatchDidClearWindowObjectInWorld(world);
   1965 
   1966     if (Page* page = m_frame->page())
   1967         page->inspectorController()->didClearWindowObjectInWorld(m_frame, world);
   1968 
   1969     InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
   1970 }
   1971 
   1972 SandboxFlags FrameLoader::effectiveSandboxFlags() const
   1973 {
   1974     SandboxFlags flags = m_forcedSandboxFlags;
   1975     if (Frame* parentFrame = m_frame->tree()->parent())
   1976         flags |= parentFrame->document()->sandboxFlags();
   1977     if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement())
   1978         flags |= ownerElement->sandboxFlags();
   1979     return flags;
   1980 }
   1981 
   1982 void FrameLoader::didChangeTitle(DocumentLoader* loader)
   1983 {
   1984     if (loader == m_documentLoader) {
   1985         // Must update the entries in the back-forward list too.
   1986         history()->setCurrentItemTitle(loader->title());
   1987         m_client->dispatchDidReceiveTitle(loader->title());
   1988     }
   1989 }
   1990 
   1991 void FrameLoader::dispatchDidCommitLoad()
   1992 {
   1993     m_client->dispatchDidCommitLoad();
   1994 
   1995     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
   1996 
   1997     m_frame->page()->didCommitLoad(m_frame);
   1998 
   1999     if (m_frame->page()->mainFrame() == m_frame)
   2000         m_frame->page()->useCounter()->didCommitLoad();
   2001 
   2002 }
   2003 
   2004 } // namespace WebCore
   2005