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  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  *
     13  * 1.  Redistributions of source code must retain the above copyright
     14  *     notice, this list of conditions and the following disclaimer.
     15  * 2.  Redistributions in binary form must reproduce the above copyright
     16  *     notice, this list of conditions and the following disclaimer in the
     17  *     documentation and/or other materials provided with the distribution.
     18  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
     19  *     its contributors may be used to endorse or promote products derived
     20  *     from this software without specific prior written permission.
     21  *
     22  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     25  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 #include "config.h"
     35 #include "FrameLoader.h"
     36 
     37 #include "ApplicationCacheHost.h"
     38 #include "BackForwardController.h"
     39 #include "BeforeUnloadEvent.h"
     40 #include "MemoryCache.h"
     41 #include "CachedPage.h"
     42 #include "CachedResourceLoader.h"
     43 #include "Chrome.h"
     44 #include "ContentSecurityPolicy.h"
     45 #include "DOMImplementation.h"
     46 #include "DOMWindow.h"
     47 #include "Document.h"
     48 #include "DocumentLoadTiming.h"
     49 #include "DocumentLoader.h"
     50 #include "Editor.h"
     51 #include "EditorClient.h"
     52 #include "Element.h"
     53 #include "Event.h"
     54 #include "EventNames.h"
     55 #include "FloatRect.h"
     56 #include "FormState.h"
     57 #include "FormSubmission.h"
     58 #include "Frame.h"
     59 #include "FrameLoadRequest.h"
     60 #include "FrameLoaderClient.h"
     61 #include "FrameNetworkingContext.h"
     62 #include "FrameTree.h"
     63 #include "FrameView.h"
     64 #include "HTMLAnchorElement.h"
     65 #include "HTMLFormElement.h"
     66 #include "HTMLNames.h"
     67 #include "HTMLObjectElement.h"
     68 #include "HTTPParsers.h"
     69 #include "HistoryItem.h"
     70 #include "IconDatabase.h"
     71 #include "IconLoader.h"
     72 #include "InspectorController.h"
     73 #include "InspectorInstrumentation.h"
     74 #include "Logging.h"
     75 #include "MIMETypeRegistry.h"
     76 #include "MainResourceLoader.h"
     77 #include "Page.h"
     78 #include "PageCache.h"
     79 #include "PageGroup.h"
     80 #include "PageTransitionEvent.h"
     81 #include "PluginData.h"
     82 #include "PluginDatabase.h"
     83 #include "PluginDocument.h"
     84 #include "ProgressTracker.h"
     85 #include "ResourceHandle.h"
     86 #include "ResourceRequest.h"
     87 #include "SchemeRegistry.h"
     88 #include "ScrollAnimator.h"
     89 #include "ScriptController.h"
     90 #include "ScriptSourceCode.h"
     91 #include "SecurityOrigin.h"
     92 #include "SegmentedString.h"
     93 #include "SerializedScriptValue.h"
     94 #include "Settings.h"
     95 #include "TextResourceDecoder.h"
     96 #include "WindowFeatures.h"
     97 #include "XMLDocumentParser.h"
     98 #include <wtf/CurrentTime.h>
     99 #include <wtf/StdLibExtras.h>
    100 #include <wtf/text/CString.h>
    101 #include <wtf/text/StringConcatenate.h>
    102 
    103 #if ENABLE(SHARED_WORKERS)
    104 #include "SharedWorkerRepository.h"
    105 #endif
    106 
    107 #if ENABLE(SVG)
    108 #include "SVGDocument.h"
    109 #include "SVGLocatable.h"
    110 #include "SVGNames.h"
    111 #include "SVGPreserveAspectRatio.h"
    112 #include "SVGSVGElement.h"
    113 #include "SVGViewElement.h"
    114 #include "SVGViewSpec.h"
    115 #endif
    116 
    117 #if ENABLE(WEB_ARCHIVE)
    118 #include "Archive.h"
    119 #include "ArchiveFactory.h"
    120 #endif
    121 
    122 #ifdef ANDROID_INSTRUMENT
    123 #include "TimeCounter.h"
    124 #include "RenderArena.h"
    125 #endif
    126 
    127 namespace WebCore {
    128 
    129 using namespace HTMLNames;
    130 
    131 #if ENABLE(SVG)
    132 using namespace SVGNames;
    133 #endif
    134 
    135 #if ENABLE(XHTMLMP)
    136 static const char defaultAcceptHeader[] = "application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html,application/xml;q=0.9,*/*;q=0.8";
    137 #else
    138 static const char defaultAcceptHeader[] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
    139 #endif
    140 
    141 static double storedTimeOfLastCompletedLoad;
    142 
    143 bool isBackForwardLoadType(FrameLoadType type)
    144 {
    145     switch (type) {
    146         case FrameLoadTypeStandard:
    147         case FrameLoadTypeReload:
    148         case FrameLoadTypeReloadFromOrigin:
    149         case FrameLoadTypeSame:
    150         case FrameLoadTypeRedirectWithLockedBackForwardList:
    151         case FrameLoadTypeReplace:
    152             return false;
    153         case FrameLoadTypeBack:
    154         case FrameLoadTypeBackWMLDeckNotAccessible:
    155         case FrameLoadTypeForward:
    156         case FrameLoadTypeIndexedBackForward:
    157             return true;
    158     }
    159     ASSERT_NOT_REACHED();
    160     return false;
    161 }
    162 
    163 static int numRequests(Document* document)
    164 {
    165     if (!document)
    166         return 0;
    167 
    168     return document->cachedResourceLoader()->requestCount();
    169 }
    170 
    171 // This is not in the FrameLoader class to emphasize that it does not depend on
    172 // private FrameLoader data, and to avoid increasing the number of public functions
    173 // with access to private data.  Since only this .cpp file needs it, making it
    174 // non-member lets us exclude it from the header file, thus keeping FrameLoader.h's
    175 // API simpler.
    176 //
    177 // FIXME: isDocumentSandboxed should eventually replace isSandboxed.
    178 static bool isDocumentSandboxed(Frame* frame, SandboxFlags mask)
    179 {
    180     return frame->document() && frame->document()->securityOrigin()->isSandboxed(mask);
    181 }
    182 
    183 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
    184     : m_frame(frame)
    185     , m_client(client)
    186     , m_policyChecker(frame)
    187     , m_history(frame)
    188     , m_notifer(frame)
    189     , m_subframeLoader(frame)
    190     , m_state(FrameStateCommittedPage)
    191     , m_loadType(FrameLoadTypeStandard)
    192     , m_delegateIsHandlingProvisionalLoadError(false)
    193     , m_quickRedirectComing(false)
    194     , m_sentRedirectNotification(false)
    195     , m_inStopAllLoaders(false)
    196     , m_isExecutingJavaScriptFormAction(false)
    197     , m_didCallImplicitClose(false)
    198     , m_wasUnloadEventEmitted(false)
    199     , m_pageDismissalEventBeingDispatched(false)
    200     , m_isComplete(false)
    201     , m_isLoadingMainResource(false)
    202     , m_needsClear(false)
    203     , m_checkTimer(this, &FrameLoader::checkTimerFired)
    204     , m_shouldCallCheckCompleted(false)
    205     , m_shouldCallCheckLoadComplete(false)
    206     , m_opener(0)
    207     , m_didPerformFirstNavigation(false)
    208     , m_loadingFromCachedPage(false)
    209     , m_suppressOpenerInNewFrame(false)
    210     , m_sandboxFlags(SandboxAll)
    211     , m_forcedSandboxFlags(SandboxNone)
    212 {
    213 }
    214 
    215 FrameLoader::~FrameLoader()
    216 {
    217     setOpener(0);
    218 
    219     HashSet<Frame*>::iterator end = m_openedFrames.end();
    220     for (HashSet<Frame*>::iterator it = m_openedFrames.begin(); it != end; ++it)
    221         (*it)->loader()->m_opener = 0;
    222 
    223     m_client->frameLoaderDestroyed();
    224 
    225     if (m_networkingContext)
    226         m_networkingContext->invalidate();
    227 }
    228 
    229 void FrameLoader::init()
    230 {
    231     // Propagate sandbox attributes to this Frameloader and its descendants.
    232     // This needs to be done early, so that an initial document gets correct sandbox flags in its SecurityOrigin.
    233     updateSandboxFlags();
    234 
    235     // this somewhat odd set of steps is needed to give the frame an initial empty document
    236     m_stateMachine.advanceTo(FrameLoaderStateMachine::CreatingInitialEmptyDocument);
    237     setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, "")), SubstituteData()).get());
    238     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
    239     setState(FrameStateProvisional);
    240     m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String()));
    241     m_provisionalDocumentLoader->finishedLoading();
    242     m_documentLoader->writer()->begin(KURL(), false);
    243     m_documentLoader->writer()->end();
    244     m_frame->document()->cancelParsing();
    245     m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocument);
    246     m_didCallImplicitClose = true;
    247 
    248     m_networkingContext = m_client->createNetworkingContext();
    249 }
    250 
    251 void FrameLoader::setDefersLoading(bool defers)
    252 {
    253     if (m_documentLoader)
    254         m_documentLoader->setDefersLoading(defers);
    255     if (m_provisionalDocumentLoader)
    256         m_provisionalDocumentLoader->setDefersLoading(defers);
    257     if (m_policyDocumentLoader)
    258         m_policyDocumentLoader->setDefersLoading(defers);
    259 
    260     if (!defers) {
    261         m_frame->navigationScheduler()->startTimer();
    262         startCheckCompleteTimer();
    263     }
    264 }
    265 
    266 bool FrameLoader::canHandleRequest(const ResourceRequest& request)
    267 {
    268     return m_client->canHandleRequest(request);
    269 }
    270 
    271 void FrameLoader::changeLocation(PassRefPtr<SecurityOrigin> securityOrigin, const KURL& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool refresh)
    272 {
    273     RefPtr<Frame> protect(m_frame);
    274     urlSelected(FrameLoadRequest(securityOrigin, ResourceRequest(url, referrer, refresh ? ReloadIgnoringCacheData : UseProtocolCachePolicy), "_self"),
    275         0, lockHistory, lockBackForwardList, SendReferrer, ReplaceDocumentIfJavaScriptURL);
    276 }
    277 
    278 void FrameLoader::urlSelected(const KURL& url, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, ReferrerPolicy referrerPolicy)
    279 {
    280     urlSelected(FrameLoadRequest(m_frame->document()->securityOrigin(), ResourceRequest(url), passedTarget),
    281         triggeringEvent, lockHistory, lockBackForwardList, referrerPolicy, DoNotReplaceDocumentIfJavaScriptURL);
    282 }
    283 
    284 // The shouldReplaceDocumentIfJavaScriptURL parameter will go away when the FIXME to eliminate the
    285 // corresponding parameter from ScriptController::executeIfJavaScriptURL() is addressed.
    286 void FrameLoader::urlSelected(const FrameLoadRequest& passedRequest, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, ReferrerPolicy referrerPolicy, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL)
    287 {
    288     ASSERT(!m_suppressOpenerInNewFrame);
    289 
    290     FrameLoadRequest frameRequest(passedRequest);
    291 
    292     if (m_frame->script()->executeIfJavaScriptURL(frameRequest.resourceRequest().url(), shouldReplaceDocumentIfJavaScriptURL))
    293         return;
    294 
    295     if (frameRequest.frameName().isEmpty())
    296         frameRequest.setFrameName(m_frame->document()->baseTarget());
    297 
    298     if (referrerPolicy == NoReferrer)
    299         m_suppressOpenerInNewFrame = true;
    300     if (frameRequest.resourceRequest().httpReferrer().isEmpty())
    301         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
    302     addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
    303 
    304     loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0, referrerPolicy);
    305 
    306     m_suppressOpenerInNewFrame = false;
    307 }
    308 
    309 void FrameLoader::submitForm(PassRefPtr<FormSubmission> submission)
    310 {
    311     ASSERT(submission->method() == FormSubmission::PostMethod || submission->method() == FormSubmission::GetMethod);
    312 
    313     // FIXME: Find a good spot for these.
    314     ASSERT(submission->data());
    315     ASSERT(submission->state());
    316     ASSERT(submission->state()->sourceFrame() == m_frame);
    317 
    318     if (!m_frame->page())
    319         return;
    320 
    321     if (submission->action().isEmpty())
    322         return;
    323 
    324     if (isDocumentSandboxed(m_frame, SandboxForms))
    325         return;
    326 
    327     if (protocolIsJavaScript(submission->action())) {
    328         m_isExecutingJavaScriptFormAction = true;
    329         m_frame->script()->executeIfJavaScriptURL(submission->action(), DoNotReplaceDocumentIfJavaScriptURL);
    330         m_isExecutingJavaScriptFormAction = false;
    331         return;
    332     }
    333 
    334     Frame* targetFrame = m_frame->tree()->find(submission->target());
    335     if (!shouldAllowNavigation(targetFrame))
    336         return;
    337     if (!targetFrame) {
    338         if (!DOMWindow::allowPopUp(m_frame) && !isProcessingUserGesture())
    339             return;
    340 
    341         targetFrame = m_frame;
    342     } else
    343         submission->clearTarget();
    344 
    345     if (!targetFrame->page())
    346         return;
    347 
    348     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
    349 
    350     // We do not want to submit more than one form from the same page, nor do we want to submit a single
    351     // form more than once. This flag prevents these from happening; not sure how other browsers prevent this.
    352     // The flag is reset in each time we start handle a new mouse or key down event, and
    353     // also in setView since this part may get reused for a page from the back/forward cache.
    354     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
    355 
    356     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
    357     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
    358     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
    359 
    360     if (m_frame->tree()->isDescendantOf(targetFrame)) {
    361         if (m_submittedFormURL == submission->action())
    362             return;
    363         m_submittedFormURL = submission->action();
    364     }
    365 
    366     submission->data()->generateFiles(m_frame->document());
    367     submission->setReferrer(m_outgoingReferrer);
    368     submission->setOrigin(outgoingOrigin());
    369 
    370     targetFrame->navigationScheduler()->scheduleFormSubmission(submission);
    371 }
    372 
    373 void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
    374 {
    375     if (m_frame->document() && m_frame->document()->parser())
    376         m_frame->document()->parser()->stopParsing();
    377 
    378     if (unloadEventPolicy != UnloadEventPolicyNone) {
    379         if (m_frame->document()) {
    380             if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
    381                 Node* currentFocusedNode = m_frame->document()->focusedNode();
    382                 if (currentFocusedNode)
    383                     currentFocusedNode->aboutToUnload();
    384 // ANDROID
    385                 // See http://b/issue?id=5264509
    386                 if (m_frame->domWindow() && !m_pageDismissalEventBeingDispatched) {
    387                     m_pageDismissalEventBeingDispatched = true;
    388 // END ANDROID
    389                     if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide)
    390                         m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document());
    391                     if (!m_frame->document()->inPageCache()) {
    392                         RefPtr<Event> unloadEvent(Event::create(eventNames().unloadEvent, false, false));
    393                         // The DocumentLoader (and thus its DocumentLoadTiming) might get destroyed
    394                         // while dispatching the event, so protect it to prevent writing the end
    395                         // time into freed memory.
    396                         RefPtr<DocumentLoader> documentLoader = m_provisionalDocumentLoader;
    397                         if (documentLoader && !documentLoader->timing()->unloadEventStart && !documentLoader->timing()->unloadEventEnd) {
    398                             DocumentLoadTiming* timing = documentLoader->timing();
    399                             ASSERT(timing->navigationStart);
    400                             m_frame->domWindow()->dispatchTimedEvent(unloadEvent, m_frame->domWindow()->document(), &timing->unloadEventStart, &timing->unloadEventEnd);
    401                         } else
    402                             m_frame->domWindow()->dispatchEvent(unloadEvent, m_frame->domWindow()->document());
    403                     }
    404                 }
    405                 m_pageDismissalEventBeingDispatched = false;
    406                 if (m_frame->document())
    407                     m_frame->document()->updateStyleIfNeeded();
    408                 m_wasUnloadEventEmitted = true;
    409             }
    410         }
    411 
    412         // Dispatching the unload event could have made m_frame->document() null.
    413         if (m_frame->document() && !m_frame->document()->inPageCache()) {
    414             // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
    415             bool keepEventListeners = m_stateMachine.isDisplayingInitialEmptyDocument() && m_provisionalDocumentLoader
    416                 && m_frame->document()->securityOrigin()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
    417 
    418             if (!keepEventListeners)
    419                 m_frame->document()->removeAllEventListeners();
    420         }
    421     }
    422 
    423     m_isComplete = true; // to avoid calling completed() in finishedParsing()
    424     m_isLoadingMainResource = false;
    425     m_didCallImplicitClose = true; // don't want that one either
    426 
    427     if (m_frame->document() && m_frame->document()->parsing()) {
    428         finishedParsing();
    429         m_frame->document()->setParsing(false);
    430     }
    431 
    432     m_workingURL = KURL();
    433 
    434     if (Document* doc = m_frame->document()) {
    435         // FIXME: HTML5 doesn't tell us to set the state to complete when aborting, but we do anyway to match legacy behavior.
    436         // http://www.w3.org/Bugs/Public/show_bug.cgi?id=10537
    437         doc->setReadyState(Document::Complete);
    438 
    439         if (CachedResourceLoader* cachedResourceLoader = doc->cachedResourceLoader())
    440             cachedResourceLoader->cancelRequests();
    441 
    442 #if ENABLE(DATABASE)
    443         doc->stopDatabases(0);
    444 #endif
    445     }
    446 
    447     // FIXME: This will cancel redirection timer, which really needs to be restarted when restoring the frame from b/f cache.
    448     m_frame->navigationScheduler()->cancel();
    449 }
    450 
    451 void FrameLoader::stop()
    452 {
    453     // http://bugs.webkit.org/show_bug.cgi?id=10854
    454     // The frame's last ref may be removed and it will be deleted by checkCompleted().
    455     RefPtr<Frame> protector(m_frame);
    456 
    457     if (m_frame->document()->parser())
    458         m_frame->document()->parser()->stopParsing();
    459     m_frame->document()->finishParsing();
    460 
    461     if (m_iconLoader)
    462         m_iconLoader->stopLoading();
    463 }
    464 
    465 bool FrameLoader::closeURL()
    466 {
    467     history()->saveDocumentState();
    468 
    469     // Should only send the pagehide event here if the current document exists and has not been placed in the page cache.
    470     Document* currentDocument = m_frame->document();
    471     stopLoading(currentDocument && !currentDocument->inPageCache() ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly);
    472 
    473     m_frame->editor()->clearUndoRedoOperations();
    474     return true;
    475 }
    476 
    477 KURL FrameLoader::iconURL()
    478 {
    479     // If this isn't a top level frame, return nothing
    480     if (m_frame->tree() && m_frame->tree()->parent())
    481         return KURL();
    482 
    483     // If we have an iconURL from a Link element, return that
    484     if (!m_frame->document()->iconURL().isEmpty())
    485         return KURL(ParsedURLString, m_frame->document()->iconURL());
    486 
    487     // Don't return a favicon iconURL unless we're http or https
    488     KURL documentURL = m_frame->document()->url();
    489     if (!documentURL.protocolInHTTPFamily())
    490         return KURL();
    491 
    492     KURL url;
    493     bool couldSetProtocol = url.setProtocol(documentURL.protocol());
    494     ASSERT_UNUSED(couldSetProtocol, couldSetProtocol);
    495     url.setHost(documentURL.host());
    496     if (documentURL.hasPort())
    497         url.setPort(documentURL.port());
    498     url.setPath("/favicon.ico");
    499     return url;
    500 }
    501 
    502 bool FrameLoader::didOpenURL(const KURL& url)
    503 {
    504     if (m_frame->navigationScheduler()->redirectScheduledDuringLoad()) {
    505         // A redirect was scheduled before the document was created.
    506         // This can happen when one frame changes another frame's location.
    507         return false;
    508     }
    509 
    510     m_frame->navigationScheduler()->cancel();
    511     m_frame->editor()->clearLastEditCommand();
    512 
    513     m_isComplete = false;
    514     m_isLoadingMainResource = true;
    515     m_didCallImplicitClose = false;
    516 
    517     // If we are still in the process of initializing an empty document then
    518     // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
    519     // since it may cause clients to attempt to render the frame.
    520     if (!m_stateMachine.creatingInitialEmptyDocument()) {
    521         if (DOMWindow* window = m_frame->existingDOMWindow()) {
    522             window->setStatus(String());
    523             window->setDefaultStatus(String());
    524         }
    525     }
    526     m_workingURL = url;
    527     if (m_workingURL.protocolInHTTPFamily() && !m_workingURL.host().isEmpty() && m_workingURL.path().isEmpty())
    528         m_workingURL.setPath("/");
    529 
    530     started();
    531 
    532     return true;
    533 }
    534 
    535 void FrameLoader::didExplicitOpen()
    536 {
    537     m_isComplete = false;
    538     m_didCallImplicitClose = false;
    539 
    540     // Calling document.open counts as committing the first real document load.
    541     if (!m_stateMachine.committedFirstRealDocumentLoad())
    542         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
    543 
    544     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
    545     // from a subsequent window.document.open / window.document.write call.
    546     // Canceling redirection here works for all cases because document.open
    547     // implicitly precedes document.write.
    548     m_frame->navigationScheduler()->cancel();
    549 }
    550 
    551 
    552 void FrameLoader::cancelAndClear()
    553 {
    554     m_frame->navigationScheduler()->cancel();
    555 
    556     if (!m_isComplete)
    557         closeURL();
    558 
    559     clear(false);
    560     m_frame->script()->updatePlatformScriptObjects();
    561 }
    562 
    563 void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView)
    564 {
    565     m_frame->editor()->clear();
    566 
    567     if (!m_needsClear)
    568         return;
    569     m_needsClear = false;
    570 
    571     if (!m_frame->document()->inPageCache()) {
    572         m_frame->document()->cancelParsing();
    573         m_frame->document()->stopActiveDOMObjects();
    574         if (m_frame->document()->attached()) {
    575             m_frame->document()->willRemove();
    576             m_frame->document()->detach();
    577 
    578             m_frame->document()->removeFocusedNodeOfSubtree(m_frame->document());
    579         }
    580     }
    581 
    582     // Do this after detaching the document so that the unload event works.
    583     if (clearWindowProperties) {
    584         m_frame->clearDOMWindow();
    585         m_frame->script()->clearWindowShell(m_frame->document()->inPageCache());
    586     }
    587 
    588     m_frame->selection()->clear();
    589     m_frame->eventHandler()->clear();
    590     if (clearFrameView && m_frame->view())
    591         m_frame->view()->clear();
    592 
    593     // Do not drop the document before the ScriptController and view are cleared
    594     // as some destructors might still try to access the document.
    595     m_frame->setDocument(0);
    596 
    597     m_subframeLoader.clear();
    598 
    599     if (clearScriptObjects)
    600         m_frame->script()->clearScriptObjects();
    601 
    602     m_frame->navigationScheduler()->clear();
    603 
    604     m_checkTimer.stop();
    605     m_shouldCallCheckCompleted = false;
    606     m_shouldCallCheckLoadComplete = false;
    607 
    608     if (m_stateMachine.isDisplayingInitialEmptyDocument() && m_stateMachine.committedFirstRealDocumentLoad())
    609         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
    610 }
    611 
    612 void FrameLoader::receivedFirstData()
    613 {
    614     activeDocumentLoader()->writer()->begin(m_workingURL, false);
    615     activeDocumentLoader()->writer()->setDocumentWasLoadedAsPartOfNavigation();
    616 
    617     dispatchDidCommitLoad();
    618     dispatchDidClearWindowObjectsInAllWorlds();
    619 
    620     if (m_documentLoader) {
    621         StringWithDirection ptitle = m_documentLoader->title();
    622         // If we have a title let the WebView know about it.
    623         if (!ptitle.isNull())
    624             m_client->dispatchDidReceiveTitle(ptitle);
    625     }
    626 
    627     m_workingURL = KURL();
    628 
    629     double delay;
    630     String url;
    631     if (!m_documentLoader)
    632         return;
    633     if (m_frame->inViewSourceMode())
    634         return;
    635     if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField("Refresh"), false, delay, url))
    636         return;
    637 
    638     if (url.isEmpty())
    639         url = m_frame->document()->url().string();
    640     else
    641         url = m_frame->document()->completeURL(url).string();
    642 
    643     m_frame->navigationScheduler()->scheduleRedirect(delay, url);
    644 }
    645 
    646 void FrameLoader::setOutgoingReferrer(const KURL& url)
    647 {
    648     m_outgoingReferrer = url.strippedForUseAsReferrer();
    649 }
    650 
    651 void FrameLoader::didBeginDocument(bool dispatch)
    652 {
    653     m_needsClear = true;
    654     m_isComplete = false;
    655     m_didCallImplicitClose = false;
    656     m_isLoadingMainResource = true;
    657     m_frame->document()->setReadyState(Document::Loading);
    658 
    659     if (m_pendingStateObject) {
    660         m_frame->document()->statePopped(m_pendingStateObject.get());
    661         m_pendingStateObject.clear();
    662     }
    663 
    664     if (dispatch)
    665         dispatchDidClearWindowObjectsInAllWorlds();
    666 
    667     updateFirstPartyForCookies();
    668 
    669     Settings* settings = m_frame->document()->settings();
    670     m_frame->document()->cachedResourceLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically());
    671 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
    672     m_frame->document()->cachedResourceLoader()->setBlockNetworkImage(settings && settings->blockNetworkImage());
    673 #endif
    674 
    675     if (m_documentLoader) {
    676         String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
    677         if (!dnsPrefetchControl.isEmpty())
    678             m_frame->document()->parseDNSPrefetchControlHeader(dnsPrefetchControl);
    679 
    680         String contentSecurityPolicy = m_documentLoader->response().httpHeaderField("X-WebKit-CSP");
    681         if (!contentSecurityPolicy.isEmpty())
    682             m_frame->document()->contentSecurityPolicy()->didReceiveHeader(contentSecurityPolicy);
    683     }
    684 
    685     history()->restoreDocumentState();
    686 }
    687 
    688 void FrameLoader::didEndDocument()
    689 {
    690     m_isLoadingMainResource = false;
    691 }
    692 
    693 // Callback for the old-style synchronous IconDatabase interface.
    694 void FrameLoader::iconLoadDecisionReceived(IconLoadDecision iconLoadDecision)
    695 {
    696     if (!m_mayLoadIconLater)
    697         return;
    698     LOG(IconDatabase, "FrameLoader %p was told a load decision is available for its icon", this);
    699     continueIconLoadWithDecision(iconLoadDecision);
    700     m_mayLoadIconLater = false;
    701 }
    702 
    703 void FrameLoader::startIconLoader()
    704 {
    705     // FIXME: We kick off the icon loader when the frame is done receiving its main resource.
    706     // But we should instead do it when we're done parsing the head element.
    707     if (!isLoadingMainFrame())
    708         return;
    709 
    710     if (!iconDatabase().isEnabled())
    711         return;
    712 
    713     KURL url(iconURL());
    714     String urlString(url.string());
    715     if (urlString.isEmpty())
    716         return;
    717 
    718     // People who want to avoid loading images generally want to avoid loading all images, unless an exception has been made for site icons.
    719     // Now that we've accounted for URL mapping, avoid starting the network load if images aren't set to display automatically.
    720     Settings* settings = m_frame->settings();
    721     if (settings && !settings->loadsImagesAutomatically() && !settings->loadsSiteIconsIgnoringImageLoadingSetting())
    722         return;
    723 
    724     // If we're reloading the page, always start the icon load now.
    725     if (loadType() == FrameLoadTypeReload && loadType() == FrameLoadTypeReloadFromOrigin) {
    726         continueIconLoadWithDecision(IconLoadYes);
    727         return;
    728     }
    729 
    730     if (iconDatabase().supportsAsynchronousMode()) {
    731         m_documentLoader->getIconLoadDecisionForIconURL(urlString);
    732         // Commit the icon url mapping to the database just in case we don't end up loading later.
    733         commitIconURLToIconDatabase(url);
    734         return;
    735     }
    736 
    737     IconLoadDecision decision = iconDatabase().synchronousLoadDecisionForIconURL(urlString, m_documentLoader.get());
    738 
    739     if (decision == IconLoadUnknown) {
    740         // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database
    741         // just in case we don't end up loading later - if we commit the mapping a second time after the load, that's no big deal
    742         // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the
    743         // icon is later read in from disk
    744         LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data());
    745         m_mayLoadIconLater = true;
    746         m_client->registerForIconNotification();
    747         commitIconURLToIconDatabase(url);
    748         return;
    749     }
    750 
    751     continueIconLoadWithDecision(decision);
    752 }
    753 
    754 void FrameLoader::continueIconLoadWithDecision(IconLoadDecision iconLoadDecision)
    755 {
    756     ASSERT(iconLoadDecision != IconLoadUnknown);
    757 
    758     //  FIXME (<rdar://problem/9168605>) - We should support in-memory-only private browsing icons in asynchronous icon database mode.
    759     if (iconDatabase().supportsAsynchronousMode() && m_frame->page()->settings()->privateBrowsingEnabled())
    760         return;
    761 
    762     if (iconLoadDecision == IconLoadNo) {
    763         KURL url(iconURL());
    764         String urlString(url.string());
    765 
    766         LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data());
    767         commitIconURLToIconDatabase(url);
    768 
    769         if (iconDatabase().supportsAsynchronousMode()) {
    770             m_documentLoader->getIconDataForIconURL(urlString);
    771             return;
    772         }
    773 
    774         // We were told not to load this icon - that means this icon is already known by the database
    775         // If the icon data hasn't been read in from disk yet, kick off the read of the icon from the database to make sure someone
    776         // has done it. This is after registering for the notification so the WebView can call the appropriate delegate method.
    777         // Otherwise if the icon data *is* available, notify the delegate
    778         if (!iconDatabase().synchronousIconDataKnownForIconURL(urlString)) {
    779             LOG(IconDatabase, "Told not to load icon %s but icon data is not yet available - registering for notification and requesting load from disk", urlString.ascii().data());
    780             m_client->registerForIconNotification();
    781             iconDatabase().synchronousIconForPageURL(m_frame->document()->url().string(), IntSize(0, 0));
    782             iconDatabase().synchronousIconForPageURL(originalRequestURL().string(), IntSize(0, 0));
    783         } else
    784             m_client->dispatchDidReceiveIcon();
    785 
    786         return;
    787     }
    788 
    789     if (!m_iconLoader)
    790         m_iconLoader = IconLoader::create(m_frame);
    791 
    792     m_iconLoader->startLoading();
    793 }
    794 
    795 void FrameLoader::commitIconURLToIconDatabase(const KURL& icon)
    796 {
    797     LOG(IconDatabase, "Committing iconURL %s to database for pageURLs %s and %s", icon.string().ascii().data(), m_frame->document()->url().string().ascii().data(), originalRequestURL().string().ascii().data());
    798     iconDatabase().setIconURLForPageURL(icon.string(), m_frame->document()->url().string());
    799     iconDatabase().setIconURLForPageURL(icon.string(), originalRequestURL().string());
    800 }
    801 
    802 void FrameLoader::finishedParsing()
    803 {
    804     m_frame->injectUserScripts(InjectAtDocumentEnd);
    805 
    806     if (m_stateMachine.creatingInitialEmptyDocument())
    807         return;
    808 
    809     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
    810     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
    811     // Null-checking the FrameView indicates whether or not we're in the destructor.
    812     RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
    813 
    814     m_client->dispatchDidFinishDocumentLoad();
    815 
    816     checkCompleted();
    817 
    818     if (!m_frame->view())
    819         return; // We are being destroyed by something checkCompleted called.
    820 
    821     // Check if the scrollbars are really needed for the content.
    822     // If not, remove them, relayout, and repaint.
    823     m_frame->view()->restoreScrollbar();
    824     m_frame->view()->scrollToFragment(m_frame->document()->url());
    825 }
    826 
    827 void FrameLoader::loadDone()
    828 {
    829     checkCompleted();
    830 }
    831 
    832 bool FrameLoader::allChildrenAreComplete() const
    833 {
    834     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
    835         if (!child->loader()->m_isComplete)
    836             return false;
    837     }
    838     return true;
    839 }
    840 
    841 bool FrameLoader::allAncestorsAreComplete() const
    842 {
    843     for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) {
    844         if (!ancestor->loader()->m_isComplete)
    845             return false;
    846     }
    847     return true;
    848 }
    849 
    850 void FrameLoader::checkCompleted()
    851 {
    852     m_shouldCallCheckCompleted = false;
    853 
    854     if (m_frame->view())
    855         m_frame->view()->checkStopDelayingDeferredRepaints();
    856 
    857     // Have we completed before?
    858     if (m_isComplete)
    859         return;
    860 
    861     // Are we still parsing?
    862     if (m_frame->document()->parsing())
    863         return;
    864 
    865     // Still waiting for images/scripts?
    866     if (numRequests(m_frame->document()))
    867         return;
    868 
    869     // Still waiting for elements that don't go through a FrameLoader?
    870     if (m_frame->document()->isDelayingLoadEvent())
    871         return;
    872 
    873     // Any frame that hasn't completed yet?
    874     if (!allChildrenAreComplete())
    875         return;
    876 
    877     // OK, completed.
    878     m_isComplete = true;
    879     m_frame->document()->setReadyState(Document::Complete);
    880 
    881     RefPtr<Frame> protect(m_frame);
    882     checkCallImplicitClose(); // if we didn't do it before
    883 
    884     m_frame->navigationScheduler()->startTimer();
    885 
    886     completed();
    887     if (m_frame->page())
    888         checkLoadComplete();
    889 }
    890 
    891 void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
    892 {
    893     if (Page* page = m_frame->page()) {
    894         if (page->defersLoading())
    895             return;
    896     }
    897     if (m_shouldCallCheckCompleted)
    898         checkCompleted();
    899     if (m_shouldCallCheckLoadComplete)
    900         checkLoadComplete();
    901 }
    902 
    903 void FrameLoader::startCheckCompleteTimer()
    904 {
    905     if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
    906         return;
    907     if (m_checkTimer.isActive())
    908         return;
    909     m_checkTimer.startOneShot(0);
    910 }
    911 
    912 void FrameLoader::scheduleCheckCompleted()
    913 {
    914     m_shouldCallCheckCompleted = true;
    915     startCheckCompleteTimer();
    916 }
    917 
    918 void FrameLoader::scheduleCheckLoadComplete()
    919 {
    920     m_shouldCallCheckLoadComplete = true;
    921     startCheckCompleteTimer();
    922 }
    923 
    924 void FrameLoader::checkCallImplicitClose()
    925 {
    926     if (m_didCallImplicitClose || m_frame->document()->parsing() || m_frame->document()->isDelayingLoadEvent())
    927         return;
    928 
    929     if (!allChildrenAreComplete())
    930         return; // still got a frame running -> too early
    931 
    932     m_didCallImplicitClose = true;
    933     m_wasUnloadEventEmitted = false;
    934     m_frame->document()->implicitClose();
    935 }
    936 
    937 KURL FrameLoader::baseURL() const
    938 {
    939     ASSERT(m_frame->document());
    940     return m_frame->document()->baseURL();
    941 }
    942 
    943 KURL FrameLoader::completeURL(const String& url)
    944 {
    945     ASSERT(m_frame->document());
    946     return m_frame->document()->completeURL(url);
    947 }
    948 
    949 void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
    950 {
    951     ASSERT(childFrame);
    952 
    953 #if ENABLE(WEB_ARCHIVE)
    954     RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->uniqueName());
    955     if (subframeArchive) {
    956         childFrame->loader()->loadArchive(subframeArchive.release());
    957         return;
    958     }
    959 #endif // ENABLE(WEB_ARCHIVE)
    960 
    961     HistoryItem* parentItem = history()->currentItem();
    962     // If we're moving in the back/forward list, we might want to replace the content
    963     // of this child frame with whatever was there at that point.
    964     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType())) {
    965         HistoryItem* childItem = parentItem->childItemWithTarget(childFrame->tree()->uniqueName());
    966         if (childItem) {
    967             childFrame->loader()->loadDifferentDocumentItem(childItem, loadType());
    968             return;
    969         }
    970     }
    971 
    972     childFrame->loader()->loadURL(url, referer, String(), false, FrameLoadTypeRedirectWithLockedBackForwardList, 0, 0);
    973 }
    974 
    975 #if ENABLE(WEB_ARCHIVE)
    976 void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive)
    977 {
    978     RefPtr<Archive> archive = prpArchive;
    979 
    980     ArchiveResource* mainResource = archive->mainResource();
    981     ASSERT(mainResource);
    982     if (!mainResource)
    983         return;
    984 
    985     SubstituteData substituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
    986 
    987     ResourceRequest request(mainResource->url());
    988 #if PLATFORM(MAC)
    989     request.applyWebArchiveHackForMail();
    990 #endif
    991 
    992     RefPtr<DocumentLoader> documentLoader = m_client->createDocumentLoader(request, substituteData);
    993     documentLoader->addAllArchiveResources(archive.get());
    994     load(documentLoader.get());
    995 }
    996 #endif // ENABLE(WEB_ARCHIVE)
    997 
    998 ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn, bool shouldPreferPlugInsForImages)
    999 {
   1000     String mimeType = mimeTypeIn;
   1001     String extension = url.path().substring(url.path().reverseFind('.') + 1);
   1002 
   1003     // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure
   1004     if (mimeType.isEmpty())
   1005         mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
   1006 
   1007 #if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL
   1008     if (mimeType.isEmpty())
   1009         mimeType = PluginDatabase::installedPlugins()->MIMETypeForExtension(extension);
   1010 #endif
   1011 
   1012     if (mimeType.isEmpty())
   1013         return ObjectContentFrame; // Go ahead and hope that we can display the content.
   1014 
   1015 #if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) && !PLATFORM(EFL) // Mac has no PluginDatabase, nor does Chromium or EFL
   1016     bool plugInSupportsMIMEType = PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType);
   1017 #else
   1018     bool plugInSupportsMIMEType = false;
   1019 #endif
   1020 
   1021     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
   1022         return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? WebCore::ObjectContentNetscapePlugin : WebCore::ObjectContentImage;
   1023 
   1024     if (plugInSupportsMIMEType)
   1025         return WebCore::ObjectContentNetscapePlugin;
   1026 
   1027     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
   1028         return WebCore::ObjectContentFrame;
   1029 
   1030     return WebCore::ObjectContentNone;
   1031 }
   1032 
   1033 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
   1034 void FrameLoader::hideMediaPlayerProxyPlugin(Widget* widget)
   1035 {
   1036     m_client->hideMediaPlayerProxyPlugin(widget);
   1037 }
   1038 
   1039 void FrameLoader::showMediaPlayerProxyPlugin(Widget* widget)
   1040 {
   1041     m_client->showMediaPlayerProxyPlugin(widget);
   1042 }
   1043 #endif // ENABLE(PLUGIN_PROXY_FOR_VIDEO)
   1044 
   1045 String FrameLoader::outgoingReferrer() const
   1046 {
   1047     return m_outgoingReferrer;
   1048 }
   1049 
   1050 String FrameLoader::outgoingOrigin() const
   1051 {
   1052     return m_frame->document()->securityOrigin()->toString();
   1053 }
   1054 
   1055 bool FrameLoader::isMixedContent(SecurityOrigin* context, const KURL& url)
   1056 {
   1057     if (context->protocol() != "https")
   1058         return false;  // We only care about HTTPS security origins.
   1059 
   1060     if (!url.isValid() || SchemeRegistry::shouldTreatURLSchemeAsSecure(url.protocol()))
   1061         return false;  // Loading these protocols is secure.
   1062 
   1063     return true;
   1064 }
   1065 
   1066 void FrameLoader::checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL& url)
   1067 {
   1068     if (!isMixedContent(context, url))
   1069         return;
   1070 
   1071     String message = makeString("The page at ", m_frame->document()->url().string(), " displayed insecure content from ", url.string(), ".\n");
   1072     m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String());
   1073 
   1074     m_client->didDisplayInsecureContent();
   1075 }
   1076 
   1077 void FrameLoader::checkIfRunInsecureContent(SecurityOrigin* context, const KURL& url)
   1078 {
   1079     if (!isMixedContent(context, url))
   1080         return;
   1081 
   1082     String message = makeString("The page at ", m_frame->document()->url().string(), " ran insecure content from ", url.string(), ".\n");
   1083     m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String());
   1084 
   1085     m_client->didRunInsecureContent(context, url);
   1086 }
   1087 
   1088 Frame* FrameLoader::opener()
   1089 {
   1090     return m_opener;
   1091 }
   1092 
   1093 void FrameLoader::setOpener(Frame* opener)
   1094 {
   1095     if (m_opener)
   1096         m_opener->loader()->m_openedFrames.remove(m_frame);
   1097     if (opener)
   1098         opener->loader()->m_openedFrames.add(m_frame);
   1099     m_opener = opener;
   1100 
   1101     if (m_frame->document()) {
   1102         m_frame->document()->initSecurityContext();
   1103         m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin());
   1104     }
   1105 }
   1106 
   1107 // FIXME: This does not belong in FrameLoader!
   1108 void FrameLoader::handleFallbackContent()
   1109 {
   1110     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
   1111     if (!owner || !owner->hasTagName(objectTag))
   1112         return;
   1113     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
   1114 }
   1115 
   1116 void FrameLoader::provisionalLoadStarted()
   1117 {
   1118 #ifdef ANDROID_INSTRUMENT
   1119     if (!m_frame->tree()->parent())
   1120         android::TimeCounter::reset();
   1121 #endif
   1122     if (m_stateMachine.firstLayoutDone())
   1123         m_stateMachine.advanceTo(FrameLoaderStateMachine::CommittedFirstRealLoad);
   1124     m_frame->navigationScheduler()->cancel(true);
   1125     m_client->provisionalLoadStarted();
   1126 }
   1127 
   1128 bool FrameLoader::isProcessingUserGesture()
   1129 {
   1130     Frame* frame = m_frame->tree()->top();
   1131     if (!frame->script()->canExecuteScripts(NotAboutToExecuteScript))
   1132         return true; // If JavaScript is disabled, a user gesture must have initiated the navigation.
   1133     return ScriptController::processingUserGesture(); // FIXME: Use pageIsProcessingUserGesture.
   1134 }
   1135 
   1136 void FrameLoader::resetMultipleFormSubmissionProtection()
   1137 {
   1138     m_submittedFormURL = KURL();
   1139 }
   1140 
   1141 void FrameLoader::willSetEncoding()
   1142 {
   1143     if (!m_workingURL.isEmpty())
   1144         receivedFirstData();
   1145 }
   1146 
   1147 #if ENABLE(WML)
   1148 static inline bool frameContainsWMLContent(Frame* frame)
   1149 {
   1150     Document* document = frame ? frame->document() : 0;
   1151     if (!document)
   1152         return false;
   1153 
   1154     return document->containsWMLContent() || document->isWMLDocument();
   1155 }
   1156 #endif
   1157 
   1158 void FrameLoader::updateFirstPartyForCookies()
   1159 {
   1160     if (m_frame->tree()->parent())
   1161         setFirstPartyForCookies(m_frame->tree()->parent()->document()->firstPartyForCookies());
   1162     else
   1163         setFirstPartyForCookies(m_frame->document()->url());
   1164 }
   1165 
   1166 void FrameLoader::setFirstPartyForCookies(const KURL& url)
   1167 {
   1168     m_frame->document()->setFirstPartyForCookies(url);
   1169     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   1170         child->loader()->setFirstPartyForCookies(url);
   1171 }
   1172 
   1173 // This does the same kind of work that didOpenURL does, except it relies on the fact
   1174 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
   1175 void FrameLoader::loadInSameDocument(const KURL& url, SerializedScriptValue* stateObject, bool isNewNavigation)
   1176 {
   1177     // If we have a state object, we cannot also be a new navigation.
   1178     ASSERT(!stateObject || (stateObject && !isNewNavigation));
   1179 
   1180     // Update the data source's request with the new URL to fake the URL change
   1181     KURL oldURL = m_frame->document()->url();
   1182     m_frame->document()->setURL(url);
   1183     documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
   1184     if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
   1185         // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add
   1186         // based on the current request. Must also happen before we openURL and displace the
   1187         // scroll position, since adding the BF item will save away scroll state.
   1188 
   1189         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
   1190         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
   1191         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
   1192         // though its load is not yet done.  I think this all works out OK, for one because
   1193         // we have already saved away the scroll and doc state for the long slow load,
   1194         // but it's not an obvious case.
   1195 
   1196         history()->updateBackForwardListForFragmentScroll();
   1197     }
   1198 
   1199     bool hashChange = equalIgnoringFragmentIdentifier(url, oldURL) && url.fragmentIdentifier() != oldURL.fragmentIdentifier();
   1200 
   1201     history()->updateForSameDocumentNavigation();
   1202 
   1203     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
   1204     if (hashChange)
   1205         m_frame->eventHandler()->stopAutoscrollTimer();
   1206 
   1207     // It's important to model this as a load that starts and immediately finishes.
   1208     // Otherwise, the parent frame may think we never finished loading.
   1209     started();
   1210 
   1211     // We need to scroll to the fragment whether or not a hash change occurred, since
   1212     // the user might have scrolled since the previous navigation.
   1213     if (FrameView* view = m_frame->view())
   1214         view->scrollToFragment(url);
   1215 
   1216     m_isComplete = false;
   1217     checkCompleted();
   1218 
   1219     if (isNewNavigation) {
   1220         // This will clear previousItem from the rest of the frame tree that didn't
   1221         // doing any loading. We need to make a pass on this now, since for anchor nav
   1222         // we'll not go through a real load and reach Completed state.
   1223         checkLoadComplete();
   1224     }
   1225 
   1226     m_client->dispatchDidNavigateWithinPage();
   1227 
   1228     m_frame->document()->statePopped(stateObject ? stateObject : SerializedScriptValue::nullValue());
   1229     m_client->dispatchDidPopStateWithinPage();
   1230 
   1231     if (hashChange) {
   1232         m_frame->document()->enqueueHashchangeEvent(oldURL, url);
   1233         m_client->dispatchDidChangeLocationWithinPage();
   1234     }
   1235 
   1236     // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
   1237     m_client->didFinishLoad();
   1238 }
   1239 
   1240 bool FrameLoader::isComplete() const
   1241 {
   1242     return m_isComplete;
   1243 }
   1244 
   1245 void FrameLoader::completed()
   1246 {
   1247     RefPtr<Frame> protect(m_frame);
   1248 
   1249     for (Frame* descendant = m_frame->tree()->traverseNext(m_frame); descendant; descendant = descendant->tree()->traverseNext(m_frame))
   1250         descendant->navigationScheduler()->startTimer();
   1251 
   1252     if (Frame* parent = m_frame->tree()->parent())
   1253         parent->loader()->checkCompleted();
   1254 
   1255     if (m_frame->view())
   1256         m_frame->view()->maintainScrollPositionAtAnchor(0);
   1257 }
   1258 
   1259 void FrameLoader::started()
   1260 {
   1261     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
   1262         frame->loader()->m_isComplete = false;
   1263 }
   1264 
   1265 void FrameLoader::prepareForLoadStart()
   1266 {
   1267     if (Page* page = m_frame->page())
   1268         page->progress()->progressStarted(m_frame);
   1269     m_client->dispatchDidStartProvisionalLoad();
   1270 }
   1271 
   1272 void FrameLoader::setupForReplace()
   1273 {
   1274     setState(FrameStateProvisional);
   1275     m_provisionalDocumentLoader = m_documentLoader;
   1276     m_documentLoader = 0;
   1277     detachChildren();
   1278 }
   1279 
   1280 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
   1281 {
   1282     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
   1283 }
   1284 
   1285 // This is a hack to allow keep navigation to http/https feeds working. To remove this
   1286 // we need to introduce new API akin to registerURLSchemeAsLocal, that registers a
   1287 // protocols navigation policy.
   1288 static bool isFeedWithNestedProtocolInHTTPFamily(const KURL& url)
   1289 {
   1290     const String& urlString = url.string();
   1291     if (!urlString.startsWith("feed", false))
   1292         return false;
   1293 
   1294     return urlString.startsWith("feed://", false)
   1295         || urlString.startsWith("feed:http:", false) || urlString.startsWith("feed:https:", false)
   1296         || urlString.startsWith("feeds:http:", false) || urlString.startsWith("feeds:https:", false)
   1297         || urlString.startsWith("feedsearch:http:", false) || urlString.startsWith("feedsearch:https:", false);
   1298 }
   1299 
   1300 void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList,
   1301     PassRefPtr<Event> event, PassRefPtr<FormState> formState, ReferrerPolicy referrerPolicy)
   1302 {
   1303     KURL url = request.resourceRequest().url();
   1304 
   1305     ASSERT(m_frame->document());
   1306     // FIXME: Should we move the isFeedWithNestedProtocolInHTTPFamily logic inside SecurityOrigin::canDisplay?
   1307     if (!isFeedWithNestedProtocolInHTTPFamily(url) && !request.requester()->canDisplay(url)) {
   1308         reportLocalLoadFailed(m_frame, url.string());
   1309         return;
   1310     }
   1311 
   1312     String referrer;
   1313     String argsReferrer = request.resourceRequest().httpReferrer();
   1314     if (!argsReferrer.isEmpty())
   1315         referrer = argsReferrer;
   1316     else
   1317         referrer = m_outgoingReferrer;
   1318 
   1319     if (SecurityOrigin::shouldHideReferrer(url, referrer) || referrerPolicy == NoReferrer)
   1320         referrer = String();
   1321 
   1322     FrameLoadType loadType;
   1323     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
   1324         loadType = FrameLoadTypeReload;
   1325     else if (lockBackForwardList)
   1326         loadType = FrameLoadTypeRedirectWithLockedBackForwardList;
   1327     else
   1328         loadType = FrameLoadTypeStandard;
   1329 
   1330     if (request.resourceRequest().httpMethod() == "POST")
   1331         loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.get());
   1332     else
   1333         loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.get());
   1334 
   1335     // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
   1336     // load if frame names have changed.
   1337     Frame* sourceFrame = formState ? formState->sourceFrame() : m_frame;
   1338     Frame* targetFrame = sourceFrame->loader()->findFrameForNavigation(request.frameName());
   1339     if (targetFrame && targetFrame != sourceFrame) {
   1340         if (Page* page = targetFrame->page())
   1341             page->chrome()->focus();
   1342     }
   1343 }
   1344 
   1345 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
   1346     PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState)
   1347 {
   1348     if (m_inStopAllLoaders)
   1349         return;
   1350 
   1351     RefPtr<FormState> formState = prpFormState;
   1352     bool isFormSubmission = formState;
   1353 
   1354     ResourceRequest request(newURL);
   1355     if (!referrer.isEmpty()) {
   1356         request.setHTTPReferrer(referrer);
   1357         RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
   1358         addHTTPOriginIfNeeded(request, referrerOrigin->toString());
   1359     }
   1360     addExtraFieldsToRequest(request, newLoadType, true, event || isFormSubmission);
   1361     if (newLoadType == FrameLoadTypeReload || newLoadType == FrameLoadTypeReloadFromOrigin)
   1362         request.setCachePolicy(ReloadIgnoringCacheData);
   1363 
   1364     ASSERT(newLoadType != FrameLoadTypeSame);
   1365 
   1366     // The search for a target frame is done earlier in the case of form submission.
   1367     Frame* targetFrame = isFormSubmission ? 0 : findFrameForNavigation(frameName);
   1368     if (targetFrame && targetFrame != m_frame) {
   1369         targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState.release());
   1370         return;
   1371     }
   1372 
   1373     if (m_pageDismissalEventBeingDispatched)
   1374         return;
   1375 
   1376     NavigationAction action(newURL, newLoadType, isFormSubmission, event);
   1377 
   1378     if (!targetFrame && !frameName.isEmpty()) {
   1379         policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy,
   1380             request, formState.release(), frameName, this);
   1381         return;
   1382     }
   1383 
   1384     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
   1385 
   1386     bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
   1387     const String& httpMethod = request.httpMethod();
   1388 
   1389     // Make sure to do scroll to anchor processing even if the URL is
   1390     // exactly the same so pages with '#' links and DHTML side effects
   1391     // work properly.
   1392     if (shouldScrollToAnchor(isFormSubmission, httpMethod, newLoadType, newURL)) {
   1393         oldDocumentLoader->setTriggeringAction(action);
   1394         policyChecker()->stopCheck();
   1395         policyChecker()->setLoadType(newLoadType);
   1396         policyChecker()->checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
   1397             callContinueFragmentScrollAfterNavigationPolicy, this);
   1398     } else {
   1399         // must grab this now, since this load may stop the previous load and clear this flag
   1400         bool isRedirect = m_quickRedirectComing;
   1401         loadWithNavigationAction(request, action, lockHistory, newLoadType, formState.release());
   1402         if (isRedirect) {
   1403             m_quickRedirectComing = false;
   1404             if (m_provisionalDocumentLoader)
   1405                 m_provisionalDocumentLoader->setIsClientRedirect(true);
   1406         } else if (sameURL)
   1407             // Example of this case are sites that reload the same URL with a different cookie
   1408             // driving the generated content, or a master frame with links that drive a target
   1409             // frame, where the user has clicked on the same link repeatedly.
   1410             m_loadType = FrameLoadTypeSame;
   1411     }
   1412 }
   1413 
   1414 void FrameLoader::load(const ResourceRequest& request, bool lockHistory)
   1415 {
   1416     load(request, SubstituteData(), lockHistory);
   1417 }
   1418 
   1419 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData, bool lockHistory)
   1420 {
   1421     if (m_inStopAllLoaders)
   1422         return;
   1423 
   1424     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
   1425     m_loadType = FrameLoadTypeStandard;
   1426     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData);
   1427     if (lockHistory && m_documentLoader)
   1428         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
   1429     load(loader.get());
   1430 }
   1431 
   1432 void FrameLoader::load(const ResourceRequest& request, const String& frameName, bool lockHistory)
   1433 {
   1434     if (frameName.isEmpty()) {
   1435         load(request, lockHistory);
   1436         return;
   1437     }
   1438 
   1439     Frame* frame = findFrameForNavigation(frameName);
   1440     if (frame) {
   1441         frame->loader()->load(request, lockHistory);
   1442         return;
   1443     }
   1444 
   1445     policyChecker()->checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), FrameLoader::callContinueLoadAfterNewWindowPolicy, request, 0, frameName, this);
   1446 }
   1447 
   1448 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState)
   1449 {
   1450     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
   1451     if (lockHistory && m_documentLoader)
   1452         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory().string() : m_documentLoader->clientRedirectSourceForHistory());
   1453 
   1454     loader->setTriggeringAction(action);
   1455     if (m_documentLoader)
   1456         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   1457 
   1458     loadWithDocumentLoader(loader.get(), type, formState);
   1459 }
   1460 
   1461 void FrameLoader::load(DocumentLoader* newDocumentLoader)
   1462 {
   1463     ResourceRequest& r = newDocumentLoader->request();
   1464     addExtraFieldsToMainResourceRequest(r);
   1465     FrameLoadType type;
   1466 
   1467     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
   1468         r.setCachePolicy(ReloadIgnoringCacheData);
   1469         type = FrameLoadTypeSame;
   1470     } else
   1471         type = FrameLoadTypeStandard;
   1472 
   1473     if (m_documentLoader)
   1474         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   1475 
   1476     // When we loading alternate content for an unreachable URL that we're
   1477     // visiting in the history list, we treat it as a reload so the history list
   1478     // is appropriately maintained.
   1479     //
   1480     // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadTypeReload" ...
   1481     // shouldn't a more explicit type of reload be defined, that means roughly
   1482     // "load without affecting history" ?
   1483     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
   1484         // shouldReloadToHandleUnreachableURL() returns true only when the original load type is back-forward.
   1485         // In this case we should save the document state now. Otherwise the state can be lost because load type is
   1486         // changed and updateForBackForwardNavigation() will not be called when loading is committed.
   1487         history()->saveDocumentAndScrollState();
   1488 
   1489         ASSERT(type == FrameLoadTypeStandard);
   1490         type = FrameLoadTypeReload;
   1491     }
   1492 
   1493     loadWithDocumentLoader(newDocumentLoader, type, 0);
   1494 }
   1495 
   1496 void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState)
   1497 {
   1498     // Retain because dispatchBeforeLoadEvent may release the last reference to it.
   1499     RefPtr<Frame> protect(m_frame);
   1500 
   1501     ASSERT(m_client->hasWebView());
   1502 
   1503     // Unfortunately the view must be non-nil, this is ultimately due
   1504     // to parser requiring a FrameView.  We should fix this dependency.
   1505 
   1506     ASSERT(m_frame->view());
   1507 
   1508     if (m_pageDismissalEventBeingDispatched)
   1509         return;
   1510 
   1511     if (m_frame->document())
   1512         m_previousUrl = m_frame->document()->url();
   1513 
   1514     policyChecker()->setLoadType(type);
   1515     RefPtr<FormState> formState = prpFormState;
   1516     bool isFormSubmission = formState;
   1517 
   1518     const KURL& newURL = loader->request().url();
   1519     const String& httpMethod = loader->request().httpMethod();
   1520 
   1521     if (shouldScrollToAnchor(isFormSubmission,  httpMethod, policyChecker()->loadType(), newURL)) {
   1522         RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
   1523         NavigationAction action(newURL, policyChecker()->loadType(), isFormSubmission);
   1524 
   1525         oldDocumentLoader->setTriggeringAction(action);
   1526         policyChecker()->stopCheck();
   1527         policyChecker()->checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
   1528             callContinueFragmentScrollAfterNavigationPolicy, this);
   1529     } else {
   1530         if (Frame* parent = m_frame->tree()->parent())
   1531             loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
   1532 
   1533         policyChecker()->stopCheck();
   1534         setPolicyDocumentLoader(loader);
   1535         if (loader->triggeringAction().isEmpty())
   1536             loader->setTriggeringAction(NavigationAction(newURL, policyChecker()->loadType(), isFormSubmission));
   1537 
   1538         if (Element* ownerElement = m_frame->ownerElement()) {
   1539             if (!ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) {
   1540                 continueLoadAfterNavigationPolicy(loader->request(), formState, false);
   1541                 return;
   1542             }
   1543         }
   1544 
   1545         policyChecker()->checkNavigationPolicy(loader->request(), loader, formState,
   1546             callContinueLoadAfterNavigationPolicy, this);
   1547     }
   1548 }
   1549 
   1550 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
   1551 {
   1552     ASSERT(!url.isEmpty());
   1553     if (!frame)
   1554         return;
   1555 
   1556     frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
   1557 }
   1558 
   1559 const ResourceRequest& FrameLoader::initialRequest() const
   1560 {
   1561     return activeDocumentLoader()->originalRequest();
   1562 }
   1563 
   1564 bool FrameLoader::willLoadMediaElementURL(KURL& url)
   1565 {
   1566     ResourceRequest request(url);
   1567 
   1568     unsigned long identifier;
   1569     ResourceError error;
   1570     requestFromDelegate(request, identifier, error);
   1571     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), -1, -1, error);
   1572 
   1573     url = request.url();
   1574 
   1575     return error.isNull();
   1576 }
   1577 
   1578 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
   1579 {
   1580     KURL unreachableURL = docLoader->unreachableURL();
   1581 
   1582     if (unreachableURL.isEmpty())
   1583         return false;
   1584 
   1585     if (!isBackForwardLoadType(policyChecker()->loadType()))
   1586         return false;
   1587 
   1588     // We only treat unreachableURLs specially during the delegate callbacks
   1589     // for provisional load errors and navigation policy decisions. The former
   1590     // case handles well-formed URLs that can't be loaded, and the latter
   1591     // case handles malformed URLs and unknown schemes. Loading alternate content
   1592     // at other times behaves like a standard load.
   1593     DocumentLoader* compareDocumentLoader = 0;
   1594     if (policyChecker()->delegateIsDecidingNavigationPolicy() || policyChecker()->delegateIsHandlingUnimplementablePolicy())
   1595         compareDocumentLoader = m_policyDocumentLoader.get();
   1596     else if (m_delegateIsHandlingProvisionalLoadError)
   1597         compareDocumentLoader = m_provisionalDocumentLoader.get();
   1598 
   1599     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
   1600 }
   1601 
   1602 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
   1603 {
   1604     if (!m_documentLoader)
   1605         return;
   1606 
   1607     ResourceRequest request = m_documentLoader->request();
   1608     KURL unreachableURL = m_documentLoader->unreachableURL();
   1609     if (!unreachableURL.isEmpty())
   1610         request.setURL(unreachableURL);
   1611 
   1612     request.setCachePolicy(ReturnCacheDataElseLoad);
   1613 
   1614     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
   1615     setPolicyDocumentLoader(loader.get());
   1616 
   1617     loader->setOverrideEncoding(encoding);
   1618 
   1619     loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
   1620 }
   1621 
   1622 void FrameLoader::reload(bool endToEndReload)
   1623 {
   1624     if (!m_documentLoader)
   1625         return;
   1626 
   1627     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
   1628     // Reloading in this case will lose the current contents (see 4151001).
   1629     if (m_documentLoader->request().url().isEmpty())
   1630         return;
   1631 
   1632     ResourceRequest initialRequest = m_documentLoader->request();
   1633 
   1634     // Replace error-page URL with the URL we were trying to reach.
   1635     KURL unreachableURL = m_documentLoader->unreachableURL();
   1636     if (!unreachableURL.isEmpty())
   1637         initialRequest.setURL(unreachableURL);
   1638 
   1639     // Create a new document loader for the reload, this will become m_documentLoader eventually,
   1640     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
   1641     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
   1642 
   1643     ResourceRequest& request = loader->request();
   1644 
   1645     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
   1646     request.setCachePolicy(ReloadIgnoringCacheData);
   1647 
   1648     // If we're about to re-post, set up action so the application can warn the user.
   1649     if (request.httpMethod() == "POST")
   1650         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
   1651 
   1652     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   1653 
   1654     loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, 0);
   1655 }
   1656 
   1657 static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
   1658 {
   1659     // targetFrame can be NULL when we're trying to navigate a top-level frame
   1660     // that has a NULL opener.
   1661     if (!targetFrame)
   1662         return false;
   1663 
   1664     const bool isLocalActiveOrigin = activeSecurityOrigin->isLocal();
   1665     for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
   1666         Document* ancestorDocument = ancestorFrame->document();
   1667         if (!ancestorDocument)
   1668             return true;
   1669 
   1670         const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
   1671         if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
   1672             return true;
   1673 
   1674         // Allow file URL descendant navigation even when allowFileAccessFromFileURLs is false.
   1675         if (isLocalActiveOrigin && ancestorSecurityOrigin->isLocal())
   1676             return true;
   1677     }
   1678 
   1679     return false;
   1680 }
   1681 
   1682 bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
   1683 {
   1684     // The navigation change is safe if the active frame is:
   1685     //   - in the same security origin as the target or one of the target's
   1686     //     ancestors.
   1687     //
   1688     // Or the target frame is:
   1689     //   - a top-level frame in the frame hierarchy and the active frame can
   1690     //     navigate the target frame's opener per above or it is the opener of
   1691     //     the target frame.
   1692 
   1693     if (!targetFrame)
   1694         return true;
   1695 
   1696     // Performance optimization.
   1697     if (m_frame == targetFrame)
   1698         return true;
   1699 
   1700     // Let a frame navigate the top-level window that contains it.  This is
   1701     // important to allow because it lets a site "frame-bust" (escape from a
   1702     // frame created by another web site).
   1703     if (!isDocumentSandboxed(m_frame, SandboxTopNavigation) && targetFrame == m_frame->tree()->top())
   1704         return true;
   1705 
   1706     // A sandboxed frame can only navigate itself and its descendants.
   1707     if (isDocumentSandboxed(m_frame, SandboxNavigation) && !targetFrame->tree()->isDescendantOf(m_frame))
   1708         return false;
   1709 
   1710     // Let a frame navigate its opener if the opener is a top-level window.
   1711     if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetFrame)
   1712         return true;
   1713 
   1714     Document* activeDocument = m_frame->document();
   1715     ASSERT(activeDocument);
   1716     const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
   1717 
   1718     // For top-level windows, check the opener.
   1719     if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin, targetFrame->loader()->opener()))
   1720         return true;
   1721 
   1722     // In general, check the frame's ancestors.
   1723     if (canAccessAncestor(activeSecurityOrigin, targetFrame))
   1724         return true;
   1725 
   1726     Settings* settings = targetFrame->settings();
   1727     if (settings && !settings->privateBrowsingEnabled()) {
   1728         Document* targetDocument = targetFrame->document();
   1729         // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
   1730         String message = makeString("Unsafe JavaScript attempt to initiate a navigation change for frame with URL ",
   1731                                     targetDocument->url().string(), " from frame with URL ", activeDocument->url().string(), ".\n");
   1732 
   1733         // FIXME: should we print to the console of the activeFrame as well?
   1734         targetFrame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
   1735     }
   1736 
   1737     return false;
   1738 }
   1739 
   1740 void FrameLoader::stopLoadingSubframes(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
   1741 {
   1742     for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   1743         child->loader()->stopAllLoaders(clearProvisionalItemPolicy);
   1744 }
   1745 
   1746 void FrameLoader::stopAllLoaders(ClearProvisionalItemPolicy clearProvisionalItemPolicy)
   1747 {
   1748     ASSERT(!m_frame->document() || !m_frame->document()->inPageCache());
   1749     if (m_pageDismissalEventBeingDispatched)
   1750         return;
   1751 
   1752     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
   1753     if (m_inStopAllLoaders)
   1754         return;
   1755 
   1756     m_inStopAllLoaders = true;
   1757 
   1758     policyChecker()->stopCheck();
   1759 
   1760     // If no new load is in progress, we should clear the provisional item from history
   1761     // before we call stopLoading.
   1762     if (clearProvisionalItemPolicy == ShouldClearProvisionalItem)
   1763         history()->setProvisionalItem(0);
   1764 
   1765     stopLoadingSubframes(clearProvisionalItemPolicy);
   1766     if (m_provisionalDocumentLoader)
   1767         m_provisionalDocumentLoader->stopLoading();
   1768     if (m_documentLoader)
   1769         m_documentLoader->stopLoading();
   1770 
   1771     setProvisionalDocumentLoader(0);
   1772 
   1773 #if ENABLE(WEB_ARCHIVE)
   1774     if (m_documentLoader)
   1775         m_documentLoader->clearArchiveResources();
   1776 #endif
   1777 
   1778     m_checkTimer.stop();
   1779 
   1780     m_inStopAllLoaders = false;
   1781 }
   1782 
   1783 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
   1784 {
   1785     stopAllLoaders();
   1786 
   1787     if (deferCheckLoadComplete)
   1788         scheduleCheckLoadComplete();
   1789     else if (m_frame->page())
   1790         checkLoadComplete();
   1791 }
   1792 
   1793 DocumentLoader* FrameLoader::activeDocumentLoader() const
   1794 {
   1795     if (m_state == FrameStateProvisional)
   1796         return m_provisionalDocumentLoader.get();
   1797     return m_documentLoader.get();
   1798 }
   1799 
   1800 bool FrameLoader::isLoading() const
   1801 {
   1802     DocumentLoader* docLoader = activeDocumentLoader();
   1803     if (!docLoader)
   1804         return false;
   1805     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
   1806 }
   1807 
   1808 bool FrameLoader::frameHasLoaded() const
   1809 {
   1810     return m_stateMachine.committedFirstRealDocumentLoad() || (m_provisionalDocumentLoader && !m_stateMachine.creatingInitialEmptyDocument());
   1811 }
   1812 
   1813 void FrameLoader::transferLoadingResourcesFromPage(Page* oldPage)
   1814 {
   1815     ASSERT(oldPage != m_frame->page());
   1816     if (isLoading()) {
   1817         activeDocumentLoader()->transferLoadingResourcesFromPage(oldPage);
   1818         oldPage->progress()->progressCompleted(m_frame);
   1819         if (m_frame->page())
   1820             m_frame->page()->progress()->progressStarted(m_frame);
   1821     }
   1822 }
   1823 
   1824 void FrameLoader::dispatchTransferLoadingResourceFromPage(unsigned long identifier, DocumentLoader* docLoader, const ResourceRequest& request, Page* oldPage)
   1825 {
   1826     notifier()->dispatchTransferLoadingResourceFromPage(identifier, docLoader, request, oldPage);
   1827 }
   1828 
   1829 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
   1830 {
   1831     if (!loader && !m_documentLoader)
   1832         return;
   1833 
   1834     ASSERT(loader != m_documentLoader);
   1835     ASSERT(!loader || loader->frameLoader() == this);
   1836 
   1837     m_client->prepareForDataSourceReplacement();
   1838     detachChildren();
   1839     if (m_documentLoader)
   1840         m_documentLoader->detachFromFrame();
   1841 
   1842     m_documentLoader = loader;
   1843 
   1844     // The following abomination is brought to you by the unload event.
   1845     // The detachChildren() call above may trigger a child frame's unload event,
   1846     // which could do something obnoxious like call document.write("") on
   1847     // the main frame, which results in detaching children while detaching children.
   1848     // This can cause the new m_documentLoader to be detached from its Frame*, but still
   1849     // be alive. To make matters worse, DocumentLoaders with a null Frame* aren't supposed
   1850     // to happen when they're still alive (and many places below us on the stack think the
   1851     // DocumentLoader is still usable). Ergo, we reattach loader to its Frame, and pretend
   1852     // like nothing ever happened.
   1853     if (m_documentLoader && !m_documentLoader->frame()) {
   1854         ASSERT(!m_documentLoader->isLoading());
   1855         m_documentLoader->setFrame(m_frame);
   1856     }
   1857 }
   1858 
   1859 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
   1860 {
   1861     if (m_policyDocumentLoader == loader)
   1862         return;
   1863 
   1864     ASSERT(m_frame);
   1865     if (loader)
   1866         loader->setFrame(m_frame);
   1867     if (m_policyDocumentLoader
   1868             && m_policyDocumentLoader != m_provisionalDocumentLoader
   1869             && m_policyDocumentLoader != m_documentLoader)
   1870         m_policyDocumentLoader->detachFromFrame();
   1871 
   1872     m_policyDocumentLoader = loader;
   1873 }
   1874 
   1875 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
   1876 {
   1877     ASSERT(!loader || !m_provisionalDocumentLoader);
   1878     ASSERT(!loader || loader->frameLoader() == this);
   1879 
   1880     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
   1881         m_provisionalDocumentLoader->detachFromFrame();
   1882 
   1883     m_provisionalDocumentLoader = loader;
   1884 }
   1885 
   1886 double FrameLoader::timeOfLastCompletedLoad()
   1887 {
   1888     return storedTimeOfLastCompletedLoad;
   1889 }
   1890 
   1891 void FrameLoader::setState(FrameState newState)
   1892 {
   1893     m_state = newState;
   1894 
   1895     if (newState == FrameStateProvisional)
   1896         provisionalLoadStarted();
   1897     else if (newState == FrameStateComplete) {
   1898         frameLoadCompleted();
   1899         storedTimeOfLastCompletedLoad = currentTime();
   1900         if (m_documentLoader)
   1901             m_documentLoader->stopRecordingResponses();
   1902     }
   1903 }
   1904 
   1905 void FrameLoader::clearProvisionalLoad()
   1906 {
   1907     setProvisionalDocumentLoader(0);
   1908     if (Page* page = m_frame->page())
   1909         page->progress()->progressCompleted(m_frame);
   1910     setState(FrameStateComplete);
   1911 }
   1912 
   1913 void FrameLoader::markLoadComplete()
   1914 {
   1915     setState(FrameStateComplete);
   1916 }
   1917 
   1918 void FrameLoader::commitProvisionalLoad()
   1919 {
   1920     RefPtr<CachedPage> cachedPage = m_loadingFromCachedPage ? pageCache()->get(history()->provisionalItem()) : 0;
   1921     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
   1922 
   1923     LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s'", m_frame->tree()->uniqueName().string().utf8().data(),
   1924         m_frame->document() ? m_frame->document()->url().string().utf8().data() : "",
   1925         pdl ? pdl->url().string().utf8().data() : "<no provisional DocumentLoader>");
   1926 
   1927     // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
   1928     // We are doing this here because we know for sure that a new page is about to be loaded.
   1929     HistoryItem* item = history()->currentItem();
   1930     if (!m_frame->tree()->parent() && PageCache::canCache(m_frame->page()) && !item->isInPageCache())
   1931         pageCache()->add(item, m_frame->page());
   1932 
   1933     if (m_loadType != FrameLoadTypeReplace)
   1934         closeOldDataSources();
   1935 
   1936     if (!cachedPage && !m_stateMachine.creatingInitialEmptyDocument())
   1937         m_client->makeRepresentation(pdl.get());
   1938 
   1939     transitionToCommitted(cachedPage);
   1940 
   1941     if (pdl) {
   1942         // Check if the destination page is allowed to access the previous page's timing information.
   1943         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::create(pdl->request().url());
   1944         m_documentLoader->timing()->hasSameOriginAsPreviousDocument = securityOrigin->canRequest(m_previousUrl);
   1945     }
   1946 
   1947     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
   1948     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
   1949     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
   1950     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
   1951     if (m_sentRedirectNotification)
   1952         clientRedirectCancelledOrFinished(false);
   1953 
   1954     if (cachedPage && cachedPage->document()) {
   1955         prepareForCachedPageRestore();
   1956         cachedPage->restore(m_frame->page());
   1957 
   1958         dispatchDidCommitLoad();
   1959 
   1960         // If we have a title let the WebView know about it.
   1961         StringWithDirection title = m_documentLoader->title();
   1962         if (!title.isNull())
   1963             m_client->dispatchDidReceiveTitle(title);
   1964 
   1965         checkCompleted();
   1966     } else {
   1967         KURL url = pdl->substituteData().responseURL();
   1968         if (url.isEmpty())
   1969             url = pdl->url();
   1970         if (url.isEmpty())
   1971             url = pdl->responseURL();
   1972         if (url.isEmpty())
   1973             url = blankURL();
   1974 
   1975         didOpenURL(url);
   1976     }
   1977 
   1978     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->uniqueName().string().utf8().data(),
   1979         m_frame->document() ? m_frame->document()->url().string().utf8().data() : "");
   1980 
   1981     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
   1982         history()->updateForClientRedirect();
   1983 
   1984     if (m_loadingFromCachedPage) {
   1985         m_frame->document()->documentDidBecomeActive();
   1986 
   1987         // Force a layout to update view size and thereby update scrollbars.
   1988         m_frame->view()->forceLayout();
   1989 
   1990         const ResponseVector& responses = m_documentLoader->responses();
   1991         size_t count = responses.size();
   1992         for (size_t i = 0; i < count; i++) {
   1993             const ResourceResponse& response = responses[i];
   1994             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
   1995             ResourceError error;
   1996             unsigned long identifier;
   1997             ResourceRequest request(response.url());
   1998             requestFromDelegate(request, identifier, error);
   1999             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
   2000             // However, with today's computers and networking speeds, this won't happen in practice.
   2001             // Could be an issue with a giant local file.
   2002             notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, static_cast<int>(response.expectedContentLength()), 0, error);
   2003         }
   2004 
   2005         pageCache()->remove(history()->currentItem());
   2006 
   2007         m_documentLoader->setPrimaryLoadComplete(true);
   2008 
   2009         // FIXME: Why only this frame and not parent frames?
   2010         checkLoadCompleteForThisFrame();
   2011     }
   2012 }
   2013 
   2014 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
   2015 {
   2016     ASSERT(m_client->hasWebView());
   2017     ASSERT(m_state == FrameStateProvisional);
   2018 
   2019     if (m_state != FrameStateProvisional)
   2020         return;
   2021 
   2022     if (m_frame->view())
   2023         m_frame->view()->scrollAnimator()->cancelAnimations();
   2024 
   2025     m_client->setCopiesOnScroll();
   2026     history()->updateForCommit();
   2027 
   2028     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
   2029     // JavaScript. If the script initiates a new load, we need to abandon the current load,
   2030     // or the two will stomp each other.
   2031     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
   2032     if (m_documentLoader)
   2033         closeURL();
   2034     if (pdl != m_provisionalDocumentLoader)
   2035         return;
   2036 
   2037     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
   2038     if (m_documentLoader)
   2039         m_documentLoader->stopLoadingSubresources();
   2040     if (m_documentLoader)
   2041         m_documentLoader->stopLoadingPlugIns();
   2042 
   2043     setDocumentLoader(m_provisionalDocumentLoader.get());
   2044     setProvisionalDocumentLoader(0);
   2045     setState(FrameStateCommittedPage);
   2046 
   2047     // Handle adding the URL to the back/forward list.
   2048     DocumentLoader* dl = m_documentLoader.get();
   2049 
   2050     switch (m_loadType) {
   2051         case FrameLoadTypeForward:
   2052         case FrameLoadTypeBack:
   2053         case FrameLoadTypeBackWMLDeckNotAccessible:
   2054         case FrameLoadTypeIndexedBackForward:
   2055             if (m_frame->page()) {
   2056                 // If the first load within a frame is a navigation within a back/forward list that was attached
   2057                 // without any of the items being loaded then we need to update the history in a similar manner as
   2058                 // for a standard load with the exception of updating the back/forward list (<rdar://problem/8091103>).
   2059                 if (!m_stateMachine.committedFirstRealDocumentLoad())
   2060                     history()->updateForStandardLoad(HistoryController::UpdateAllExceptBackForwardList);
   2061 
   2062                 history()->updateForBackForwardNavigation();
   2063 
   2064                 // For cached pages, CachedFrame::restore will take care of firing the popstate event with the history item's state object
   2065                 if (history()->currentItem() && !cachedPage)
   2066                     m_pendingStateObject = history()->currentItem()->stateObject();
   2067 
   2068                 // Create a document view for this document, or used the cached view.
   2069                 if (cachedPage) {
   2070                     DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
   2071                     ASSERT(cachedDocumentLoader);
   2072                     cachedDocumentLoader->setFrame(m_frame);
   2073                     m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
   2074 
   2075                 } else
   2076                     m_client->transitionToCommittedForNewPage();
   2077             }
   2078             break;
   2079 
   2080         case FrameLoadTypeReload:
   2081         case FrameLoadTypeReloadFromOrigin:
   2082         case FrameLoadTypeSame:
   2083         case FrameLoadTypeReplace:
   2084             history()->updateForReload();
   2085             m_client->transitionToCommittedForNewPage();
   2086             break;
   2087 
   2088         case FrameLoadTypeStandard:
   2089             history()->updateForStandardLoad();
   2090 #ifndef BUILDING_ON_TIGER
   2091             // This code was originally added for a Leopard performance imporvement. We decided to
   2092             // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
   2093             if (m_frame->view())
   2094                 m_frame->view()->setScrollbarsSuppressed(true);
   2095 #endif
   2096             m_client->transitionToCommittedForNewPage();
   2097             break;
   2098 
   2099         case FrameLoadTypeRedirectWithLockedBackForwardList:
   2100             history()->updateForRedirectWithLockedBackForwardList();
   2101             m_client->transitionToCommittedForNewPage();
   2102             break;
   2103 
   2104         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
   2105         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
   2106         default:
   2107             ASSERT_NOT_REACHED();
   2108     }
   2109 
   2110     m_documentLoader->writer()->setMIMEType(dl->responseMIMEType());
   2111 
   2112     // Tell the client we've committed this URL.
   2113     ASSERT(m_frame->view());
   2114 
   2115     if (m_stateMachine.creatingInitialEmptyDocument())
   2116         return;
   2117 
   2118     if (!m_stateMachine.committedFirstRealDocumentLoad())
   2119         m_stateMachine.advanceTo(FrameLoaderStateMachine::DisplayingInitialEmptyDocumentPostCommit);
   2120 
   2121     if (!m_client->hasHTMLView())
   2122         receivedFirstData();
   2123 }
   2124 
   2125 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
   2126 {
   2127     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
   2128     // the redirect succeeded.  We should either rename this API, or add a new method, like
   2129     // -webView:didFinishClientRedirectForFrame:
   2130     m_client->dispatchDidCancelClientRedirect();
   2131 
   2132     if (!cancelWithLoadInProgress)
   2133         m_quickRedirectComing = false;
   2134 
   2135     m_sentRedirectNotification = false;
   2136 }
   2137 
   2138 void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockBackForwardList)
   2139 {
   2140     m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate);
   2141 
   2142     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
   2143     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
   2144     m_sentRedirectNotification = true;
   2145 
   2146     // If a "quick" redirect comes in, we set a special mode so we treat the next
   2147     // load as part of the original navigation. If we don't have a document loader, we have
   2148     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
   2149     // Loads triggered by JavaScript form submissions never count as quick redirects.
   2150     m_quickRedirectComing = (lockBackForwardList || history()->currentItemShouldBeReplaced()) && m_documentLoader && !m_isExecutingJavaScriptFormAction;
   2151 }
   2152 
   2153 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
   2154 {
   2155 #if ENABLE(WML)
   2156     // All WML decks are supposed to be reloaded, even within the same URL fragment
   2157     if (frameContainsWMLContent(m_frame))
   2158         return true;
   2159 #endif
   2160 
   2161     // This function implements the rule: "Don't reload if navigating by fragment within
   2162     // the same URL, but do reload if going to a new URL or to the same URL with no
   2163     // fragment identifier at all."
   2164     if (!destinationURL.hasFragmentIdentifier())
   2165         return true;
   2166     return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
   2167 }
   2168 
   2169 void FrameLoader::closeOldDataSources()
   2170 {
   2171     // FIXME: Is it important for this traversal to be postorder instead of preorder?
   2172     // If so, add helpers for postorder traversal, and use them. If not, then lets not
   2173     // use a recursive algorithm here.
   2174     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   2175         child->loader()->closeOldDataSources();
   2176 
   2177     if (m_documentLoader)
   2178         m_client->dispatchWillClose();
   2179 
   2180     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
   2181 }
   2182 
   2183 void FrameLoader::prepareForCachedPageRestore()
   2184 {
   2185     ASSERT(!m_frame->tree()->parent());
   2186     ASSERT(m_frame->page());
   2187     ASSERT(m_frame->page()->mainFrame() == m_frame);
   2188 
   2189     m_frame->navigationScheduler()->cancel();
   2190 
   2191     // We still have to close the previous part page.
   2192     closeURL();
   2193 
   2194     // Delete old status bar messages (if it _was_ activated on last URL).
   2195     if (m_frame->script()->canExecuteScripts(NotAboutToExecuteScript)) {
   2196         if (DOMWindow* window = m_frame->existingDOMWindow()) {
   2197             window->setStatus(String());
   2198             window->setDefaultStatus(String());
   2199         }
   2200     }
   2201 }
   2202 
   2203 void FrameLoader::open(CachedFrameBase& cachedFrame)
   2204 {
   2205     m_isComplete = false;
   2206 
   2207     // Don't re-emit the load event.
   2208     m_didCallImplicitClose = true;
   2209 
   2210     KURL url = cachedFrame.url();
   2211 
   2212     if (url.protocolInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
   2213         url.setPath("/");
   2214 
   2215     m_workingURL = url;
   2216 
   2217     started();
   2218     clear(true, true, cachedFrame.isMainFrame());
   2219 
   2220     Document* document = cachedFrame.document();
   2221     ASSERT(document);
   2222     document->setInPageCache(false);
   2223 
   2224     m_needsClear = true;
   2225     m_isComplete = false;
   2226     m_didCallImplicitClose = false;
   2227     m_outgoingReferrer = url.string();
   2228 
   2229     FrameView* view = cachedFrame.view();
   2230 
   2231     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
   2232     ASSERT(view);
   2233     view->setWasScrolledByUser(false);
   2234 
   2235     // Use the current ScrollView's frame rect.
   2236     if (m_frame->view()) {
   2237         IntRect rect = m_frame->view()->frameRect();
   2238         view->setFrameRect(rect);
   2239         view->setBoundsSize(rect.size());
   2240     }
   2241     m_frame->setView(view);
   2242 
   2243     m_frame->setDocument(document);
   2244     m_frame->setDOMWindow(cachedFrame.domWindow());
   2245     m_frame->domWindow()->setURL(document->url());
   2246     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
   2247 
   2248     updateFirstPartyForCookies();
   2249 
   2250     cachedFrame.restore();
   2251 }
   2252 
   2253 bool FrameLoader::isStopping() const
   2254 {
   2255     return activeDocumentLoader()->isStopping();
   2256 }
   2257 
   2258 void FrameLoader::finishedLoading()
   2259 {
   2260     // Retain because the stop may release the last reference to it.
   2261     RefPtr<Frame> protect(m_frame);
   2262 
   2263     RefPtr<DocumentLoader> dl = activeDocumentLoader();
   2264     dl->finishedLoading();
   2265     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
   2266         return;
   2267     dl->setPrimaryLoadComplete(true);
   2268     m_client->dispatchDidLoadMainResource(dl.get());
   2269     checkLoadComplete();
   2270 }
   2271 
   2272 bool FrameLoader::isHostedByObjectElement() const
   2273 {
   2274     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
   2275     return owner && owner->hasTagName(objectTag);
   2276 }
   2277 
   2278 bool FrameLoader::isLoadingMainFrame() const
   2279 {
   2280     Page* page = m_frame->page();
   2281     return page && m_frame == page->mainFrame();
   2282 }
   2283 
   2284 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
   2285 {
   2286     return m_client->canShowMIMEType(MIMEType);
   2287 }
   2288 
   2289 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
   2290 {
   2291     return m_client->representationExistsForURLScheme(URLScheme);
   2292 }
   2293 
   2294 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
   2295 {
   2296     return m_client->generatedMIMETypeForURLScheme(URLScheme);
   2297 }
   2298 
   2299 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
   2300 {
   2301     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
   2302 }
   2303 
   2304 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
   2305 {
   2306     // FIXME: Platforms shouldn't differ here!
   2307 #if PLATFORM(WIN) || PLATFORM(CHROMIUM) || defined(ANDROID)
   2308     if (m_stateMachine.creatingInitialEmptyDocument())
   2309         return;
   2310 #endif
   2311 
   2312 #if !ENABLE(WEB_ARCHIVE)
   2313     m_client->finishedLoading(loader);
   2314 #else
   2315     // Give archive machinery a crack at this document. If the MIME type is not an archive type, it will return 0.
   2316     RefPtr<Archive> archive = ArchiveFactory::create(loader->mainResourceData().get(), loader->responseMIMEType());
   2317     if (!archive) {
   2318         m_client->finishedLoading(loader);
   2319         return;
   2320     }
   2321 
   2322     // FIXME: The remainder of this function should be moved to DocumentLoader.
   2323 
   2324     loader->addAllArchiveResources(archive.get());
   2325 
   2326     ArchiveResource* mainResource = archive->mainResource();
   2327     loader->setParsedArchiveData(mainResource->data());
   2328 
   2329     loader->writer()->setMIMEType(mainResource->mimeType());
   2330 
   2331     closeURL();
   2332     didOpenURL(mainResource->url());
   2333 
   2334     ASSERT(m_frame->document());
   2335     String userChosenEncoding = documentLoader()->overrideEncoding();
   2336     bool encodingIsUserChosen = !userChosenEncoding.isNull();
   2337     loader->writer()->setEncoding(encodingIsUserChosen ? userChosenEncoding : mainResource->textEncoding(), encodingIsUserChosen);
   2338     loader->writer()->addData(mainResource->data()->data(), mainResource->data()->size());
   2339 #endif // ENABLE(WEB_ARCHIVE)
   2340 }
   2341 
   2342 bool FrameLoader::isReplacing() const
   2343 {
   2344     return m_loadType == FrameLoadTypeReplace;
   2345 }
   2346 
   2347 void FrameLoader::setReplacing()
   2348 {
   2349     m_loadType = FrameLoadTypeReplace;
   2350 }
   2351 
   2352 void FrameLoader::revertToProvisional(DocumentLoader* loader)
   2353 {
   2354     m_client->revertToProvisionalState(loader);
   2355 }
   2356 
   2357 bool FrameLoader::subframeIsLoading() const
   2358 {
   2359     // It's most likely that the last added frame is the last to load so we walk backwards.
   2360     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
   2361         FrameLoader* childLoader = child->loader();
   2362         DocumentLoader* documentLoader = childLoader->documentLoader();
   2363         if (documentLoader && documentLoader->isLoadingInAPISense())
   2364             return true;
   2365         documentLoader = childLoader->provisionalDocumentLoader();
   2366         if (documentLoader && documentLoader->isLoadingInAPISense())
   2367             return true;
   2368         documentLoader = childLoader->policyDocumentLoader();
   2369         if (documentLoader)
   2370             return true;
   2371     }
   2372     return false;
   2373 }
   2374 
   2375 void FrameLoader::willChangeTitle(DocumentLoader* loader)
   2376 {
   2377     m_client->willChangeTitle(loader);
   2378 }
   2379 
   2380 FrameLoadType FrameLoader::loadType() const
   2381 {
   2382     return m_loadType;
   2383 }
   2384 
   2385 CachePolicy FrameLoader::subresourceCachePolicy() const
   2386 {
   2387     if (m_isComplete)
   2388         return CachePolicyVerify;
   2389 
   2390     if (m_loadType == FrameLoadTypeReloadFromOrigin)
   2391         return CachePolicyReload;
   2392 
   2393     if (Frame* parentFrame = m_frame->tree()->parent()) {
   2394         CachePolicy parentCachePolicy = parentFrame->loader()->subresourceCachePolicy();
   2395         if (parentCachePolicy != CachePolicyVerify)
   2396             return parentCachePolicy;
   2397     }
   2398 
   2399     const ResourceRequest& request(documentLoader()->request());
   2400     Settings* settings = m_frame->settings();
   2401     if (settings && settings->useQuickLookResourceCachingQuirks() && request.cachePolicy() == ReloadIgnoringCacheData && !equalIgnoringCase(request.httpMethod(), "post"))
   2402         return CachePolicyRevalidate;
   2403 
   2404     if (m_loadType == FrameLoadTypeReload)
   2405         return CachePolicyRevalidate;
   2406 
   2407     if (request.cachePolicy() == ReturnCacheDataElseLoad)
   2408         return CachePolicyHistoryBuffer;
   2409 
   2410     return CachePolicyVerify;
   2411 }
   2412 
   2413 void FrameLoader::checkLoadCompleteForThisFrame()
   2414 {
   2415     ASSERT(m_client->hasWebView());
   2416 
   2417     switch (m_state) {
   2418         case FrameStateProvisional: {
   2419             if (m_delegateIsHandlingProvisionalLoadError)
   2420                 return;
   2421 
   2422             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
   2423             if (!pdl)
   2424                 return;
   2425 
   2426             // If we've received any errors we may be stuck in the provisional state and actually complete.
   2427             const ResourceError& error = pdl->mainDocumentError();
   2428             if (error.isNull())
   2429                 return;
   2430 
   2431             // Check all children first.
   2432             RefPtr<HistoryItem> item;
   2433             if (Page* page = m_frame->page())
   2434                 if (isBackForwardLoadType(loadType()))
   2435                     // Reset the back forward list to the last committed history item at the top level.
   2436                     item = page->mainFrame()->loader()->history()->currentItem();
   2437 
   2438             // Only reset if we aren't already going to a new provisional item.
   2439             bool shouldReset = !history()->provisionalItem();
   2440             if (!pdl->isLoadingInAPISense() || pdl->isStopping()) {
   2441                 m_delegateIsHandlingProvisionalLoadError = true;
   2442                 m_client->dispatchDidFailProvisionalLoad(error);
   2443                 m_delegateIsHandlingProvisionalLoadError = false;
   2444 
   2445                 ASSERT(!pdl->isLoading());
   2446                 ASSERT(!pdl->isLoadingMainResource());
   2447                 ASSERT(!pdl->isLoadingSubresources());
   2448                 ASSERT(!pdl->isLoadingPlugIns());
   2449 
   2450                 // If we're in the middle of loading multipart data, we need to restore the document loader.
   2451                 if (isReplacing() && !m_documentLoader.get())
   2452                     setDocumentLoader(m_provisionalDocumentLoader.get());
   2453 
   2454                 // Finish resetting the load state, but only if another load hasn't been started by the
   2455                 // delegate callback.
   2456                 if (pdl == m_provisionalDocumentLoader)
   2457                     clearProvisionalLoad();
   2458                 else if (activeDocumentLoader()) {
   2459                     KURL unreachableURL = activeDocumentLoader()->unreachableURL();
   2460                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
   2461                         shouldReset = false;
   2462                 }
   2463             }
   2464             if (shouldReset && item)
   2465                 if (Page* page = m_frame->page()) {
   2466                     page->backForward()->setCurrentItem(item.get());
   2467                     m_frame->loader()->client()->updateGlobalHistoryItemForPage();
   2468                 }
   2469             return;
   2470         }
   2471 
   2472         case FrameStateCommittedPage: {
   2473             DocumentLoader* dl = m_documentLoader.get();
   2474             if (!dl || (dl->isLoadingInAPISense() && !dl->isStopping()))
   2475                 return;
   2476 
   2477             markLoadComplete();
   2478 
   2479             // FIXME: Is this subsequent work important if we already navigated away?
   2480             // Maybe there are bugs because of that, or extra work we can skip because
   2481             // the new page is ready.
   2482 
   2483             m_client->forceLayoutForNonHTML();
   2484 
   2485             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
   2486             if (m_frame->page()) {
   2487                 if (isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin)
   2488                     history()->restoreScrollPositionAndViewState();
   2489             }
   2490 
   2491             if (m_stateMachine.creatingInitialEmptyDocument() || !m_stateMachine.committedFirstRealDocumentLoad())
   2492                 return;
   2493 
   2494             const ResourceError& error = dl->mainDocumentError();
   2495             if (!error.isNull())
   2496                 m_client->dispatchDidFailLoad(error);
   2497             else
   2498                 m_client->dispatchDidFinishLoad();
   2499 
   2500             if (Page* page = m_frame->page())
   2501                 page->progress()->progressCompleted(m_frame);
   2502 
   2503 #ifdef ANDROID_INSTRUMENT
   2504             if (!m_frame->tree()->parent() && m_frame->document()->renderArena())
   2505                 android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize(),
   2506                         m_frame->document()->renderArena()->reportPoolSize());
   2507 #endif
   2508             return;
   2509         }
   2510 
   2511         case FrameStateComplete:
   2512             frameLoadCompleted();
   2513             return;
   2514     }
   2515 
   2516     ASSERT_NOT_REACHED();
   2517 }
   2518 
   2519 void FrameLoader::continueLoadAfterWillSubmitForm()
   2520 {
   2521     if (!m_provisionalDocumentLoader)
   2522         return;
   2523 
   2524     // DocumentLoader calls back to our prepareForLoadStart
   2525     m_provisionalDocumentLoader->prepareForLoadStart();
   2526 
   2527     // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
   2528     // so we need to null check it again.
   2529     if (!m_provisionalDocumentLoader)
   2530         return;
   2531 
   2532     DocumentLoader* activeDocLoader = activeDocumentLoader();
   2533     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
   2534         return;
   2535 
   2536     m_loadingFromCachedPage = false;
   2537 
   2538     unsigned long identifier = 0;
   2539 
   2540     if (Page* page = m_frame->page()) {
   2541         identifier = page->progress()->createUniqueIdentifier();
   2542         notifier()->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
   2543     }
   2544 
   2545     ASSERT(!m_provisionalDocumentLoader->timing()->navigationStart);
   2546     m_provisionalDocumentLoader->timing()->navigationStart = currentTime();
   2547 
   2548     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
   2549         m_provisionalDocumentLoader->updateLoading();
   2550 }
   2551 
   2552 void FrameLoader::didFirstLayout()
   2553 {
   2554     if (m_frame->page() && isBackForwardLoadType(m_loadType))
   2555         history()->restoreScrollPositionAndViewState();
   2556 
   2557     if (m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
   2558         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
   2559     m_client->dispatchDidFirstLayout();
   2560 }
   2561 
   2562 void FrameLoader::didFirstVisuallyNonEmptyLayout()
   2563 {
   2564     m_client->dispatchDidFirstVisuallyNonEmptyLayout();
   2565 }
   2566 
   2567 void FrameLoader::frameLoadCompleted()
   2568 {
   2569     // Note: Can be called multiple times.
   2570 
   2571     m_client->frameLoadCompleted();
   2572 
   2573     history()->updateForFrameLoadCompleted();
   2574 
   2575     // After a canceled provisional load, firstLayoutDone is false.
   2576     // Reset it to true if we're displaying a page.
   2577     if (m_documentLoader && m_stateMachine.committedFirstRealDocumentLoad() && !m_stateMachine.isDisplayingInitialEmptyDocument() && !m_stateMachine.firstLayoutDone())
   2578         m_stateMachine.advanceTo(FrameLoaderStateMachine::FirstLayoutDone);
   2579 }
   2580 
   2581 void FrameLoader::detachChildren()
   2582 {
   2583     typedef Vector<RefPtr<Frame> > FrameVector;
   2584     FrameVector childrenToDetach;
   2585     childrenToDetach.reserveCapacity(m_frame->tree()->childCount());
   2586     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling())
   2587         childrenToDetach.append(child);
   2588     FrameVector::iterator end = childrenToDetach.end();
   2589     for (FrameVector::iterator it = childrenToDetach.begin(); it != end; it++)
   2590         (*it)->loader()->detachFromParent();
   2591 }
   2592 
   2593 void FrameLoader::closeAndRemoveChild(Frame* child)
   2594 {
   2595     child->tree()->detachFromParent();
   2596 
   2597     child->setView(0);
   2598     if (child->ownerElement() && child->page())
   2599         child->page()->decrementFrameCount();
   2600     // FIXME: The page isn't being destroyed, so it's not right to call a function named pageDestroyed().
   2601     child->pageDestroyed();
   2602 
   2603     m_frame->tree()->removeChild(child);
   2604 }
   2605 
   2606 void FrameLoader::recursiveCheckLoadComplete()
   2607 {
   2608     Vector<RefPtr<Frame>, 10> frames;
   2609 
   2610     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
   2611         frames.append(frame);
   2612 
   2613     unsigned size = frames.size();
   2614     for (unsigned i = 0; i < size; i++)
   2615         frames[i]->loader()->recursiveCheckLoadComplete();
   2616 
   2617     checkLoadCompleteForThisFrame();
   2618 }
   2619 
   2620 // Called every time a resource is completely loaded, or an error is received.
   2621 void FrameLoader::checkLoadComplete()
   2622 {
   2623     ASSERT(m_client->hasWebView());
   2624 
   2625     m_shouldCallCheckLoadComplete = false;
   2626 
   2627     // FIXME: Always traversing the entire frame tree is a bit inefficient, but
   2628     // is currently needed in order to null out the previous history item for all frames.
   2629     if (Page* page = m_frame->page())
   2630         page->mainFrame()->loader()->recursiveCheckLoadComplete();
   2631 }
   2632 
   2633 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
   2634 {
   2635     if (!recurse)
   2636         return numRequests(m_frame->document());
   2637 
   2638     int count = 0;
   2639     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
   2640         count += numRequests(frame->document());
   2641     return count;
   2642 }
   2643 
   2644 String FrameLoader::userAgent(const KURL& url) const
   2645 {
   2646     String userAgent = m_client->userAgent(url);
   2647     InspectorInstrumentation::applyUserAgentOverride(m_frame, &userAgent);
   2648     return userAgent;
   2649 }
   2650 
   2651 void FrameLoader::handledOnloadEvents()
   2652 {
   2653     m_client->dispatchDidHandleOnloadEvents();
   2654 
   2655     if (documentLoader()) {
   2656         documentLoader()->handledOnloadEvents();
   2657 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   2658         documentLoader()->applicationCacheHost()->stopDeferringEvents();
   2659 #endif
   2660     }
   2661 }
   2662 
   2663 void FrameLoader::frameDetached()
   2664 {
   2665     stopAllLoaders();
   2666     m_frame->document()->stopActiveDOMObjects();
   2667     detachFromParent();
   2668 }
   2669 
   2670 void FrameLoader::detachFromParent()
   2671 {
   2672     RefPtr<Frame> protect(m_frame);
   2673 
   2674     closeURL();
   2675     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
   2676     detachChildren();
   2677     // stopAllLoaders() needs to be called after detachChildren(), because detachedChildren()
   2678     // will trigger the unload event handlers of any child frames, and those event
   2679     // handlers might start a new subresource load in this frame.
   2680     stopAllLoaders();
   2681 
   2682     InspectorInstrumentation::frameDetachedFromParent(m_frame);
   2683 
   2684     detachViewsAndDocumentLoader();
   2685 
   2686     if (Frame* parent = m_frame->tree()->parent()) {
   2687         parent->loader()->closeAndRemoveChild(m_frame);
   2688         parent->loader()->scheduleCheckCompleted();
   2689     } else {
   2690         m_frame->setView(0);
   2691         // FIXME: The page isn't being destroyed, so it's not right to call a function named pageDestroyed().
   2692         m_frame->pageDestroyed();
   2693     }
   2694 }
   2695 
   2696 void FrameLoader::detachViewsAndDocumentLoader()
   2697 {
   2698     m_client->detachedFromParent2();
   2699     setDocumentLoader(0);
   2700     m_client->detachedFromParent3();
   2701 }
   2702 
   2703 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
   2704 {
   2705     addExtraFieldsToRequest(request, m_loadType, false, false);
   2706 }
   2707 
   2708 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
   2709 {
   2710     addExtraFieldsToRequest(request, m_loadType, true, false);
   2711 }
   2712 
   2713 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource, bool cookiePolicyURLFromRequest)
   2714 {
   2715     // Don't set the cookie policy URL if it's already been set.
   2716     // But make sure to set it on all requests, as it has significance beyond the cookie policy for all protocols (<rdar://problem/6616664>).
   2717     if (request.firstPartyForCookies().isEmpty()) {
   2718         if (mainResource && (isLoadingMainFrame() || cookiePolicyURLFromRequest))
   2719             request.setFirstPartyForCookies(request.url());
   2720         else if (Document* document = m_frame->document())
   2721             request.setFirstPartyForCookies(document->firstPartyForCookies());
   2722     }
   2723 
   2724     // The remaining modifications are only necessary for HTTP and HTTPS.
   2725     if (!request.url().isEmpty() && !request.url().protocolInHTTPFamily())
   2726         return;
   2727 
   2728     applyUserAgent(request);
   2729 
   2730     // If we inherit cache policy from a main resource, we use the DocumentLoader's
   2731     // original request cache policy for two reasons:
   2732     // 1. For POST requests, we mutate the cache policy for the main resource,
   2733     //    but we do not want this to apply to subresources
   2734     // 2. Delegates that modify the cache policy using willSendRequest: should
   2735     //    not affect any other resources. Such changes need to be done
   2736     //    per request.
   2737     if (!mainResource) {
   2738         if (request.isConditional())
   2739             request.setCachePolicy(ReloadIgnoringCacheData);
   2740         else if (documentLoader()->isLoadingInAPISense())
   2741             request.setCachePolicy(documentLoader()->originalRequest().cachePolicy());
   2742         else
   2743             request.setCachePolicy(UseProtocolCachePolicy);
   2744     } else if (loadType == FrameLoadTypeReload || loadType == FrameLoadTypeReloadFromOrigin || request.isConditional())
   2745         request.setCachePolicy(ReloadIgnoringCacheData);
   2746     else if (isBackForwardLoadType(loadType) && m_stateMachine.committedFirstRealDocumentLoad() && !request.url().protocolIs("https"))
   2747         request.setCachePolicy(ReturnCacheDataElseLoad);
   2748 
   2749     if (request.cachePolicy() == ReloadIgnoringCacheData) {
   2750         if (loadType == FrameLoadTypeReload)
   2751             request.setHTTPHeaderField("Cache-Control", "max-age=0");
   2752         else if (loadType == FrameLoadTypeReloadFromOrigin) {
   2753             request.setHTTPHeaderField("Cache-Control", "no-cache");
   2754             request.setHTTPHeaderField("Pragma", "no-cache");
   2755         }
   2756     }
   2757 
   2758     if (mainResource)
   2759         request.setHTTPAccept(defaultAcceptHeader);
   2760 
   2761     // Make sure we send the Origin header.
   2762     addHTTPOriginIfNeeded(request, String());
   2763 
   2764     // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
   2765     // For a newly opened frame with an empty URL, encoding() should not be used, because this methods asks decoder, which uses ISO-8859-1.
   2766     Settings* settings = m_frame->settings();
   2767     request.setResponseContentDispositionEncodingFallbackArray("UTF-8", activeDocumentLoader()->writer()->deprecatedFrameEncoding(), settings ? settings->defaultTextEncodingName() : String());
   2768 }
   2769 
   2770 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, String origin)
   2771 {
   2772     if (!request.httpOrigin().isEmpty())
   2773         return;  // Request already has an Origin header.
   2774 
   2775     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
   2776     // For example, if an intranet page has a hyperlink to an external web
   2777     // site, we don't want to include the Origin of the request because it
   2778     // will leak the internal host name. Similar privacy concerns have lead
   2779     // to the widespread suppression of the Referer header at the network
   2780     // layer.
   2781     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
   2782         return;
   2783 
   2784     // For non-GET and non-HEAD methods, always send an Origin header so the
   2785     // server knows we support this feature.
   2786 
   2787     if (origin.isEmpty()) {
   2788         // If we don't know what origin header to attach, we attach the value
   2789         // for an empty origin.
   2790         origin = SecurityOrigin::createEmpty()->toString();
   2791     }
   2792 
   2793     request.setHTTPOrigin(origin);
   2794 }
   2795 
   2796 void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState)
   2797 {
   2798     RefPtr<FormState> formState = prpFormState;
   2799 
   2800     // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a
   2801     // bunch of parameters that would come in here and then be built back up to a ResourceRequest.  In case
   2802     // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest
   2803     // from scratch as it did all along.
   2804     const KURL& url = inRequest.url();
   2805     RefPtr<FormData> formData = inRequest.httpBody();
   2806     const String& contentType = inRequest.httpContentType();
   2807     String origin = inRequest.httpOrigin();
   2808 
   2809     ResourceRequest workingResourceRequest(url);
   2810 
   2811     if (!referrer.isEmpty())
   2812         workingResourceRequest.setHTTPReferrer(referrer);
   2813     workingResourceRequest.setHTTPOrigin(origin);
   2814     workingResourceRequest.setHTTPMethod("POST");
   2815     workingResourceRequest.setHTTPBody(formData);
   2816     workingResourceRequest.setHTTPContentType(contentType);
   2817     addExtraFieldsToRequest(workingResourceRequest, loadType, true, true);
   2818 
   2819     NavigationAction action(url, loadType, true, event);
   2820 
   2821     if (!frameName.isEmpty()) {
   2822         // The search for a target frame is done earlier in the case of form submission.
   2823         if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName))
   2824             targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
   2825         else
   2826             policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy, workingResourceRequest, formState.release(), frameName, this);
   2827     } else
   2828         loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
   2829 }
   2830 
   2831 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data)
   2832 {
   2833     String referrer = m_outgoingReferrer;
   2834     if (SecurityOrigin::shouldHideReferrer(request.url(), referrer))
   2835         referrer = String();
   2836 
   2837     ResourceRequest initialRequest = request;
   2838     initialRequest.setTimeoutInterval(10);
   2839 
   2840     if (!referrer.isEmpty())
   2841         initialRequest.setHTTPReferrer(referrer);
   2842     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
   2843 
   2844     if (Page* page = m_frame->page())
   2845         initialRequest.setFirstPartyForCookies(page->mainFrame()->loader()->documentLoader()->request().url());
   2846     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
   2847 
   2848     addExtraFieldsToSubresourceRequest(initialRequest);
   2849 
   2850     unsigned long identifier = 0;
   2851     ResourceRequest newRequest(initialRequest);
   2852     requestFromDelegate(newRequest, identifier, error);
   2853 
   2854     if (error.isNull()) {
   2855         ASSERT(!newRequest.isNull());
   2856 
   2857 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   2858         if (!documentLoader()->applicationCacheHost()->maybeLoadSynchronously(newRequest, error, response, data)) {
   2859 #endif
   2860             ResourceHandle::loadResourceSynchronously(networkingContext(), newRequest, storedCredentials, error, response, data);
   2861 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   2862             documentLoader()->applicationCacheHost()->maybeLoadFallbackSynchronously(newRequest, error, response, data);
   2863         }
   2864 #endif
   2865     }
   2866     int encodedDataLength = response.resourceLoadInfo() ? static_cast<int>(response.resourceLoadInfo()->encodedDataLength) : -1;
   2867     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.size(), encodedDataLength, error);
   2868     return identifier;
   2869 }
   2870 
   2871 const ResourceRequest& FrameLoader::originalRequest() const
   2872 {
   2873     return activeDocumentLoader()->originalRequestCopy();
   2874 }
   2875 
   2876 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
   2877 {
   2878     // Retain because the stop may release the last reference to it.
   2879     RefPtr<Frame> protect(m_frame);
   2880 
   2881     RefPtr<DocumentLoader> loader = activeDocumentLoader();
   2882 
   2883     if (isComplete) {
   2884         // FIXME: Don't want to do this if an entirely new load is going, so should check
   2885         // that both data sources on the frame are either this or nil.
   2886         stop();
   2887         if (m_client->shouldFallBack(error))
   2888             handleFallbackContent();
   2889     }
   2890 
   2891     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
   2892         if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
   2893             m_submittedFormURL = KURL();
   2894 
   2895         // We might have made a page cache item, but now we're bailing out due to an error before we ever
   2896         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
   2897         // so that the existing view (that wenever got far enough to replace) can continue being used.
   2898         history()->invalidateCurrentItemCachedPage();
   2899 
   2900         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
   2901         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
   2902         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
   2903         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
   2904         // has ended.
   2905         if (m_sentRedirectNotification)
   2906             clientRedirectCancelledOrFinished(false);
   2907     }
   2908 
   2909     loader->mainReceivedError(error, isComplete);
   2910 }
   2911 
   2912 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
   2913     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
   2914 {
   2915     FrameLoader* loader = static_cast<FrameLoader*>(argument);
   2916     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
   2917 }
   2918 
   2919 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
   2920 {
   2921     m_quickRedirectComing = false;
   2922 
   2923     if (!shouldContinue)
   2924         return;
   2925 
   2926     bool isRedirect = m_quickRedirectComing || policyChecker()->loadType() == FrameLoadTypeRedirectWithLockedBackForwardList;
   2927     loadInSameDocument(request.url(), 0, !isRedirect);
   2928 }
   2929 
   2930 bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, const String& httpMethod, FrameLoadType loadType, const KURL& url)
   2931 {
   2932     // Should we do anchor navigation within the existing content?
   2933 
   2934     // We don't do this if we are submitting a form with method other than "GET", explicitly reloading,
   2935     // currently displaying a frameset, or if the URL does not have a fragment.
   2936     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
   2937 
   2938     // FIXME: What about load types other than Standard and Reload?
   2939 
   2940     return (!isFormSubmission || equalIgnoringCase(httpMethod, "GET"))
   2941         && loadType != FrameLoadTypeReload
   2942         && loadType != FrameLoadTypeReloadFromOrigin
   2943         && loadType != FrameLoadTypeSame
   2944         && !shouldReload(m_frame->document()->url(), url)
   2945         // We don't want to just scroll if a link from within a
   2946         // frameset is trying to reload the frameset into _top.
   2947         && !m_frame->document()->isFrameSet();
   2948 }
   2949 
   2950 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
   2951     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
   2952 {
   2953     FrameLoader* loader = static_cast<FrameLoader*>(argument);
   2954     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
   2955 }
   2956 
   2957 bool FrameLoader::shouldClose()
   2958 {
   2959     Page* page = m_frame->page();
   2960     Chrome* chrome = page ? page->chrome() : 0;
   2961     if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel())
   2962         return true;
   2963 
   2964     // Store all references to each subframe in advance since beforeunload's event handler may modify frame
   2965     Vector<RefPtr<Frame> > targetFrames;
   2966     targetFrames.append(m_frame);
   2967     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->traverseNext(m_frame))
   2968         targetFrames.append(child);
   2969 
   2970     bool shouldClose = false;
   2971     {
   2972         NavigationDisablerForBeforeUnload navigationDisabler;
   2973         size_t i;
   2974 
   2975         for (i = 0; i < targetFrames.size(); i++) {
   2976             if (!targetFrames[i]->tree()->isDescendantOf(m_frame))
   2977                 continue;
   2978             if (!targetFrames[i]->loader()->fireBeforeUnloadEvent(chrome))
   2979                 break;
   2980         }
   2981 
   2982         if (i == targetFrames.size())
   2983             shouldClose = true;
   2984     }
   2985 
   2986     return shouldClose;
   2987 }
   2988 
   2989 bool FrameLoader::fireBeforeUnloadEvent(Chrome* chrome)
   2990 {
   2991     DOMWindow* domWindow = m_frame->existingDOMWindow();
   2992     if (!domWindow)
   2993         return true;
   2994 
   2995     RefPtr<Document> document = m_frame->document();
   2996     if (!document->body())
   2997         return true;
   2998 
   2999     RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create();
   3000     m_pageDismissalEventBeingDispatched = true;
   3001     domWindow->dispatchEvent(beforeUnloadEvent.get(), domWindow->document());
   3002     m_pageDismissalEventBeingDispatched = false;
   3003 
   3004     if (!beforeUnloadEvent->defaultPrevented())
   3005         document->defaultEventHandler(beforeUnloadEvent.get());
   3006     if (beforeUnloadEvent->result().isNull())
   3007         return true;
   3008 
   3009     String text = document->displayStringModifiedByEncoding(beforeUnloadEvent->result());
   3010     return chrome->runBeforeUnloadConfirmPanel(text, m_frame);
   3011 }
   3012 
   3013 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState> formState, bool shouldContinue)
   3014 {
   3015     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
   3016     // nil policyDataSource because loading the alternate page will have passed
   3017     // through this method already, nested; otherwise, policyDataSource should still be set.
   3018     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
   3019 
   3020     bool isTargetItem = history()->provisionalItem() ? history()->provisionalItem()->isTargetItem() : false;
   3021 
   3022     // Two reasons we can't continue:
   3023     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this
   3024     //       is the user responding Cancel to the form repost nag sheet.
   3025     //    2) User responded Cancel to an alert popped up by the before unload event handler.
   3026     bool canContinue = shouldContinue && shouldClose();
   3027 
   3028     if (!canContinue) {
   3029         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we
   3030         // need to report that the client redirect was cancelled.
   3031         if (m_quickRedirectComing)
   3032             clientRedirectCancelledOrFinished(false);
   3033 
   3034         setPolicyDocumentLoader(0);
   3035 
   3036         // If the navigation request came from the back/forward menu, and we punt on it, we have the
   3037         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity,
   3038         // we only do this when punting a navigation for the target frame or top-level frame.
   3039         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(policyChecker()->loadType())) {
   3040             if (Page* page = m_frame->page()) {
   3041                 Frame* mainFrame = page->mainFrame();
   3042                 if (HistoryItem* resetItem = mainFrame->loader()->history()->currentItem()) {
   3043                     page->backForward()->setCurrentItem(resetItem);
   3044                     m_frame->loader()->client()->updateGlobalHistoryItemForPage();
   3045                 }
   3046             }
   3047         }
   3048         return;
   3049     }
   3050 
   3051     FrameLoadType type = policyChecker()->loadType();
   3052     // A new navigation is in progress, so don't clear the history's provisional item.
   3053     stopAllLoaders(ShouldNotClearProvisionalItem);
   3054 
   3055     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
   3056     // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
   3057     if (!m_frame->page())
   3058         return;
   3059 
   3060 #if ENABLE(JAVASCRIPT_DEBUGGER) && USE(JSC) && ENABLE(INSPECTOR)
   3061     if (Page* page = m_frame->page()) {
   3062         if (page->mainFrame() == m_frame)
   3063             m_frame->page()->inspectorController()->resume();
   3064     }
   3065 #endif
   3066 
   3067     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
   3068     m_loadType = type;
   3069     setState(FrameStateProvisional);
   3070 
   3071     setPolicyDocumentLoader(0);
   3072 
   3073     if (isBackForwardLoadType(type) && history()->provisionalItem()->isInPageCache()) {
   3074         loadProvisionalItemFromCachedPage();
   3075         return;
   3076     }
   3077 
   3078     if (formState)
   3079         m_client->dispatchWillSubmitForm(&PolicyChecker::continueLoadAfterWillSubmitForm, formState);
   3080     else
   3081         continueLoadAfterWillSubmitForm();
   3082 }
   3083 
   3084 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
   3085     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue)
   3086 {
   3087     FrameLoader* loader = static_cast<FrameLoader*>(argument);
   3088     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, action, shouldContinue);
   3089 }
   3090 
   3091 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
   3092     PassRefPtr<FormState> formState, const String& frameName, const NavigationAction& action, bool shouldContinue)
   3093 {
   3094     if (!shouldContinue)
   3095         return;
   3096 
   3097     RefPtr<Frame> frame = m_frame;
   3098     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(action);
   3099     if (!mainFrame)
   3100         return;
   3101 
   3102     if (frameName != "_blank")
   3103         mainFrame->tree()->setName(frameName);
   3104 
   3105     mainFrame->page()->setOpenedByDOM();
   3106     mainFrame->loader()->m_client->dispatchShow();
   3107     if (!m_suppressOpenerInNewFrame)
   3108         mainFrame->loader()->setOpener(frame.get());
   3109     mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
   3110 }
   3111 
   3112 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
   3113 {
   3114     ASSERT(!request.isNull());
   3115 
   3116     identifier = 0;
   3117     if (Page* page = m_frame->page()) {
   3118         identifier = page->progress()->createUniqueIdentifier();
   3119         notifier()->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
   3120     }
   3121 
   3122     ResourceRequest newRequest(request);
   3123     notifier()->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
   3124 
   3125     if (newRequest.isNull())
   3126         error = cancelledError(request);
   3127     else
   3128         error = ResourceError();
   3129 
   3130     request = newRequest;
   3131 }
   3132 
   3133 void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
   3134 {
   3135     Page* page = m_frame->page();
   3136     if (!page)
   3137         return;
   3138 
   3139     if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
   3140         return;
   3141 
   3142     if (!page->areMemoryCacheClientCallsEnabled()) {
   3143         InspectorInstrumentation::didLoadResourceFromMemoryCache(page, m_documentLoader.get(), resource);
   3144         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url());
   3145         m_documentLoader->didTellClientAboutLoad(resource->url());
   3146         return;
   3147     }
   3148 
   3149     ResourceRequest request(resource->url());
   3150     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize())) {
   3151         InspectorInstrumentation::didLoadResourceFromMemoryCache(page, m_documentLoader.get(), resource);
   3152         m_documentLoader->didTellClientAboutLoad(resource->url());
   3153         return;
   3154     }
   3155 
   3156     unsigned long identifier;
   3157     ResourceError error;
   3158     requestFromDelegate(request, identifier, error);
   3159     InspectorInstrumentation::markResourceAsCached(page, identifier);
   3160     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), resource->encodedSize(), 0, error);
   3161 }
   3162 
   3163 void FrameLoader::applyUserAgent(ResourceRequest& request)
   3164 {
   3165     String userAgent = this->userAgent(request.url());
   3166     ASSERT(!userAgent.isNull());
   3167     request.setHTTPUserAgent(userAgent);
   3168 }
   3169 
   3170 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url)
   3171 {
   3172     Frame* topFrame = m_frame->tree()->top();
   3173     if (m_frame == topFrame)
   3174         return false;
   3175 
   3176     if (equalIgnoringCase(content, "deny"))
   3177         return true;
   3178 
   3179     if (equalIgnoringCase(content, "sameorigin")) {
   3180         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
   3181         if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin()))
   3182             return true;
   3183     }
   3184 
   3185     return false;
   3186 }
   3187 
   3188 void FrameLoader::loadProvisionalItemFromCachedPage()
   3189 {
   3190     DocumentLoader* provisionalLoader = provisionalDocumentLoader();
   3191     LOG(PageCache, "WebCorePageCache: Loading provisional DocumentLoader %p with URL '%s' from CachedPage", provisionalDocumentLoader(), provisionalDocumentLoader()->url().string().utf8().data());
   3192 
   3193     provisionalLoader->prepareForLoadStart();
   3194 
   3195     m_loadingFromCachedPage = true;
   3196 
   3197     // Should have timing data from previous time(s) the page was shown.
   3198     ASSERT(provisionalLoader->timing()->navigationStart);
   3199     provisionalLoader->resetTiming();
   3200     provisionalLoader->timing()->navigationStart = currentTime();
   3201 
   3202     provisionalLoader->setCommitted(true);
   3203     commitProvisionalLoad();
   3204 }
   3205 
   3206 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
   3207 {
   3208     if (!history()->currentItem())
   3209         return false;
   3210     return url == history()->currentItem()->url() || url == history()->currentItem()->originalURL();
   3211 }
   3212 
   3213 void FrameLoader::checkDidPerformFirstNavigation()
   3214 {
   3215     Page* page = m_frame->page();
   3216     if (!page)
   3217         return;
   3218 
   3219     if (!m_didPerformFirstNavigation && page->backForward()->currentItem() && !page->backForward()->backItem() && !page->backForward()->forwardItem()) {
   3220         m_didPerformFirstNavigation = true;
   3221         m_client->didPerformFirstNavigation();
   3222     }
   3223 }
   3224 
   3225 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name)
   3226 {
   3227     Frame* frame = m_frame->tree()->find(name);
   3228     if (!shouldAllowNavigation(frame))
   3229         return 0;
   3230     return frame;
   3231 }
   3232 
   3233 void FrameLoader::loadSameDocumentItem(HistoryItem* item)
   3234 {
   3235     ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentSequenceNumber());
   3236 
   3237     // Save user view state to the current history item here since we don't do a normal load.
   3238     // FIXME: Does form state need to be saved here too?
   3239     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
   3240     if (FrameView* view = m_frame->view())
   3241         view->setWasScrolledByUser(false);
   3242 
   3243     history()->setCurrentItem(item);
   3244 
   3245     // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
   3246     loadInSameDocument(item->url(), item->stateObject(), false);
   3247 
   3248     // Restore user view state from the current history item here since we don't do a normal load.
   3249     history()->restoreScrollPositionAndViewState();
   3250 }
   3251 
   3252 // FIXME: This function should really be split into a couple pieces, some of
   3253 // which should be methods of HistoryController and some of which should be
   3254 // methods of FrameLoader.
   3255 void FrameLoader::loadDifferentDocumentItem(HistoryItem* item, FrameLoadType loadType)
   3256 {
   3257     // Remember this item so we can traverse any child items as child frames load
   3258     history()->setProvisionalItem(item);
   3259 
   3260     if (CachedPage* cachedPage = pageCache()->get(item)) {
   3261         loadWithDocumentLoader(cachedPage->documentLoader(), loadType, 0);
   3262         return;
   3263     }
   3264 
   3265     KURL itemURL = item->url();
   3266     KURL itemOriginalURL = item->originalURL();
   3267     KURL currentURL;
   3268     if (documentLoader())
   3269         currentURL = documentLoader()->url();
   3270     RefPtr<FormData> formData = item->formData();
   3271 
   3272     bool addedExtraFields = false;
   3273     ResourceRequest request(itemURL);
   3274 
   3275     if (!item->referrer().isNull())
   3276         request.setHTTPReferrer(item->referrer());
   3277 
   3278     // If this was a repost that failed the page cache, we might try to repost the form.
   3279     NavigationAction action;
   3280     if (formData) {
   3281         formData->generateFiles(m_frame->document());
   3282 
   3283         request.setHTTPMethod("POST");
   3284         request.setHTTPBody(formData);
   3285         request.setHTTPContentType(item->formContentType());
   3286         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer());
   3287         addHTTPOriginIfNeeded(request, securityOrigin->toString());
   3288 
   3289         // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
   3290         // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
   3291         addExtraFieldsToRequest(request, m_loadType, true, formData);
   3292         addedExtraFields = true;
   3293 
   3294         // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
   3295         // We want to know this before talking to the policy delegate, since it affects whether
   3296         // we show the DoYouReallyWantToRepost nag.
   3297         //
   3298         // This trick has a small bug (3123893) where we might find a cache hit, but then
   3299         // have the item vanish when we try to use it in the ensuing nav.  This should be
   3300         // extremely rare, but in that case the user will get an error on the navigation.
   3301 
   3302         if (ResourceHandle::willLoadFromCache(request, m_frame))
   3303             action = NavigationAction(itemURL, loadType, false);
   3304         else {
   3305             request.setCachePolicy(ReloadIgnoringCacheData);
   3306             action = NavigationAction(itemURL, NavigationTypeFormResubmitted);
   3307         }
   3308     } else {
   3309         switch (loadType) {
   3310             case FrameLoadTypeReload:
   3311             case FrameLoadTypeReloadFromOrigin:
   3312                 request.setCachePolicy(ReloadIgnoringCacheData);
   3313                 break;
   3314             case FrameLoadTypeBack:
   3315             case FrameLoadTypeBackWMLDeckNotAccessible:
   3316             case FrameLoadTypeForward:
   3317             case FrameLoadTypeIndexedBackForward:
   3318                 // If the first load within a frame is a navigation within a back/forward list that was attached
   3319                 // without any of the items being loaded then we should use the default caching policy (<rdar://problem/8131355>).
   3320                 if (m_stateMachine.committedFirstRealDocumentLoad() && !itemURL.protocolIs("https"))
   3321                     request.setCachePolicy(ReturnCacheDataElseLoad);
   3322                 break;
   3323             case FrameLoadTypeStandard:
   3324             case FrameLoadTypeRedirectWithLockedBackForwardList:
   3325                 break;
   3326             case FrameLoadTypeSame:
   3327             default:
   3328                 ASSERT_NOT_REACHED();
   3329         }
   3330 
   3331         action = NavigationAction(itemOriginalURL, loadType, false);
   3332     }
   3333 
   3334     if (!addedExtraFields)
   3335         addExtraFieldsToRequest(request, m_loadType, true, formData);
   3336 
   3337     loadWithNavigationAction(request, action, false, loadType, 0);
   3338 }
   3339 
   3340 // Loads content into this frame, as specified by history item
   3341 void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
   3342 {
   3343     HistoryItem* currentItem = history()->currentItem();
   3344     bool sameDocumentNavigation = currentItem && item->shouldDoSameDocumentNavigationTo(currentItem);
   3345 
   3346 #if ENABLE(WML)
   3347     // All WML decks should go through the real load mechanism, not the scroll-to-anchor code
   3348     // FIXME: Why do WML decks have this different behavior?
   3349     // Are WML decks incompatible with HTML5 pushState/replaceState which require inter-document history navigations?
   3350     // Should this new API be disabled for WML pages, or does WML need to update their mechanism to act like normal loads?
   3351     // If scroll-to-anchor navigations were broken for WML and required them to have different loading behavior, then
   3352     // state object loads are certainly also broken for them.
   3353     if (frameContainsWMLContent(m_frame))
   3354         sameDocumentNavigation = false;
   3355 #endif
   3356 
   3357     if (sameDocumentNavigation)
   3358         loadSameDocumentItem(item);
   3359     else
   3360         loadDifferentDocumentItem(item, loadType);
   3361 }
   3362 
   3363 void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
   3364 {
   3365     m_client->setMainDocumentError(loader, error);
   3366 }
   3367 
   3368 void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError&)
   3369 {
   3370     loader->setPrimaryLoadComplete(true);
   3371     m_client->dispatchDidLoadMainResource(activeDocumentLoader());
   3372     checkCompleted();
   3373     if (m_frame->page())
   3374         checkLoadComplete();
   3375 }
   3376 
   3377 void FrameLoader::mainReceivedError(const ResourceError& error, bool isComplete)
   3378 {
   3379     activeDocumentLoader()->mainReceivedError(error, isComplete);
   3380 }
   3381 
   3382 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
   3383 {
   3384     ResourceError error = m_client->cancelledError(request);
   3385     error.setIsCancellation(true);
   3386     return error;
   3387 }
   3388 
   3389 ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
   3390 {
   3391     return m_client->blockedError(request);
   3392 }
   3393 
   3394 ResourceError FrameLoader::cannotShowURLError(const ResourceRequest& request) const
   3395 {
   3396     return m_client->cannotShowURLError(request);
   3397 }
   3398 
   3399 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request) const
   3400 {
   3401     return m_client->interruptForPolicyChangeError(request);
   3402 }
   3403 
   3404 ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& response) const
   3405 {
   3406     return m_client->fileDoesNotExistError(response);
   3407 }
   3408 
   3409 bool FrameLoader::shouldUseCredentialStorage(ResourceLoader* loader)
   3410 {
   3411     return m_client->shouldUseCredentialStorage(loader->documentLoader(), loader->identifier());
   3412 }
   3413 
   3414 #if USE(PROTECTION_SPACE_AUTH_CALLBACK)
   3415 bool FrameLoader::canAuthenticateAgainstProtectionSpace(ResourceLoader* loader, const ProtectionSpace& protectionSpace)
   3416 {
   3417     return m_client->canAuthenticateAgainstProtectionSpace(loader->documentLoader(), loader->identifier(), protectionSpace);
   3418 }
   3419 #endif
   3420 
   3421 void FrameLoader::setTitle(const StringWithDirection& title)
   3422 {
   3423     documentLoader()->setTitle(title);
   3424 }
   3425 
   3426 void FrameLoader::setIconURL(const String& iconURL)
   3427 {
   3428     documentLoader()->setIconURL(iconURL);
   3429 }
   3430 
   3431 KURL FrameLoader::originalRequestURL() const
   3432 {
   3433     return activeDocumentLoader()->originalRequest().url();
   3434 }
   3435 
   3436 String FrameLoader::referrer() const
   3437 {
   3438     return m_documentLoader ? m_documentLoader->request().httpReferrer() : "";
   3439 }
   3440 
   3441 void FrameLoader::dispatchDocumentElementAvailable()
   3442 {
   3443     m_frame->injectUserScripts(InjectAtDocumentStart);
   3444     m_client->documentElementAvailable();
   3445 }
   3446 
   3447 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
   3448 {
   3449     if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript))
   3450         return;
   3451 
   3452     Vector<DOMWrapperWorld*> worlds;
   3453     ScriptController::getAllWorlds(worlds);
   3454     for (size_t i = 0; i < worlds.size(); ++i)
   3455         dispatchDidClearWindowObjectInWorld(worlds[i]);
   3456 }
   3457 
   3458 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
   3459 {
   3460     if (!m_frame->script()->canExecuteScripts(NotAboutToExecuteScript) || !m_frame->script()->existingWindowShell(world))
   3461         return;
   3462 
   3463     m_client->dispatchDidClearWindowObjectInWorld(world);
   3464 
   3465 #if ENABLE(INSPECTOR)
   3466     if (Page* page = m_frame->page())
   3467         page->inspectorController()->didClearWindowObjectInWorld(m_frame, world);
   3468 #endif
   3469 
   3470     InspectorInstrumentation::didClearWindowObjectInWorld(m_frame, world);
   3471 }
   3472 
   3473 void FrameLoader::updateSandboxFlags()
   3474 {
   3475     SandboxFlags flags = m_forcedSandboxFlags;
   3476     if (Frame* parentFrame = m_frame->tree()->parent())
   3477         flags |= parentFrame->loader()->sandboxFlags();
   3478     if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement())
   3479         flags |= ownerElement->sandboxFlags();
   3480 
   3481     if (m_sandboxFlags == flags)
   3482         return;
   3483 
   3484     m_sandboxFlags = flags;
   3485 
   3486     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   3487         child->loader()->updateSandboxFlags();
   3488 }
   3489 
   3490 void FrameLoader::didChangeTitle(DocumentLoader* loader)
   3491 {
   3492     m_client->didChangeTitle(loader);
   3493 
   3494     if (loader == m_documentLoader) {
   3495         // Must update the entries in the back-forward list too.
   3496         history()->setCurrentItemTitle(loader->title());
   3497         // This must go through the WebFrame because it has the right notion of the current b/f item.
   3498         m_client->setTitle(loader->title(), loader->urlForHistory());
   3499         m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
   3500         m_client->dispatchDidReceiveTitle(loader->title());
   3501     }
   3502 }
   3503 
   3504 void FrameLoader::didChangeIcons(DocumentLoader* loader)
   3505 {
   3506     if (loader == m_documentLoader)
   3507         m_client->dispatchDidChangeIcons();
   3508 }
   3509 
   3510 void FrameLoader::dispatchDidCommitLoad()
   3511 {
   3512     if (m_stateMachine.creatingInitialEmptyDocument())
   3513         return;
   3514 
   3515     m_client->dispatchDidCommitLoad();
   3516 
   3517     InspectorInstrumentation::didCommitLoad(m_frame, m_documentLoader.get());
   3518 }
   3519 
   3520 void FrameLoader::tellClientAboutPastMemoryCacheLoads()
   3521 {
   3522     ASSERT(m_frame->page());
   3523     ASSERT(m_frame->page()->areMemoryCacheClientCallsEnabled());
   3524 
   3525     if (!m_documentLoader)
   3526         return;
   3527 
   3528     Vector<String> pastLoads;
   3529     m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
   3530 
   3531     size_t size = pastLoads.size();
   3532     for (size_t i = 0; i < size; ++i) {
   3533         CachedResource* resource = memoryCache()->resourceForURL(KURL(ParsedURLString, pastLoads[i]));
   3534 
   3535         // FIXME: These loads, loaded from cache, but now gone from the cache by the time
   3536         // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
   3537         // Consider if there's some efficient way of remembering enough to deliver this client call.
   3538         // We have the URL, but not the rest of the response or the length.
   3539         if (!resource)
   3540             continue;
   3541 
   3542         ResourceRequest request(resource->url());
   3543         m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
   3544     }
   3545 }
   3546 
   3547 NetworkingContext* FrameLoader::networkingContext() const
   3548 {
   3549     return m_networkingContext.get();
   3550 }
   3551 
   3552 bool FrameLoaderClient::hasHTMLView() const
   3553 {
   3554     return true;
   3555 }
   3556 
   3557 Frame* createWindow(Frame* openerFrame, Frame* lookupFrame, const FrameLoadRequest& request, const WindowFeatures& features, bool& created)
   3558 {
   3559     ASSERT(!features.dialog || request.frameName().isEmpty());
   3560 
   3561     if (!request.frameName().isEmpty() && request.frameName() != "_blank") {
   3562         Frame* frame = lookupFrame->tree()->find(request.frameName());
   3563         if (frame && openerFrame->loader()->shouldAllowNavigation(frame)) {
   3564             if (Page* page = frame->page())
   3565                 page->chrome()->focus();
   3566             created = false;
   3567             return frame;
   3568         }
   3569     }
   3570 
   3571     // Sandboxed frames cannot open new auxiliary browsing contexts.
   3572     if (isDocumentSandboxed(openerFrame, SandboxNavigation))
   3573         return 0;
   3574 
   3575     // FIXME: Setting the referrer should be the caller's responsibility.
   3576     FrameLoadRequest requestWithReferrer = request;
   3577     requestWithReferrer.resourceRequest().setHTTPReferrer(openerFrame->loader()->outgoingReferrer());
   3578     FrameLoader::addHTTPOriginIfNeeded(requestWithReferrer.resourceRequest(), openerFrame->loader()->outgoingOrigin());
   3579 
   3580     Page* oldPage = openerFrame->page();
   3581     if (!oldPage)
   3582         return 0;
   3583 
   3584     NavigationAction action;
   3585     Page* page = oldPage->chrome()->createWindow(openerFrame, requestWithReferrer, features, action);
   3586     if (!page)
   3587         return 0;
   3588 
   3589     Frame* frame = page->mainFrame();
   3590     if (request.frameName() != "_blank")
   3591         frame->tree()->setName(request.frameName());
   3592 
   3593     page->chrome()->setToolbarsVisible(features.toolBarVisible || features.locationBarVisible);
   3594     page->chrome()->setStatusbarVisible(features.statusBarVisible);
   3595     page->chrome()->setScrollbarsVisible(features.scrollbarsVisible);
   3596     page->chrome()->setMenubarVisible(features.menuBarVisible);
   3597     page->chrome()->setResizable(features.resizable);
   3598 
   3599     // 'x' and 'y' specify the location of the window, while 'width' and 'height'
   3600     // specify the size of the page. We can only resize the window, so
   3601     // adjust for the difference between the window size and the page size.
   3602 
   3603     FloatRect windowRect = page->chrome()->windowRect();
   3604     FloatSize pageSize = page->chrome()->pageRect().size();
   3605     if (features.xSet)
   3606         windowRect.setX(features.x);
   3607     if (features.ySet)
   3608         windowRect.setY(features.y);
   3609     if (features.widthSet)
   3610         windowRect.setWidth(features.width + (windowRect.width() - pageSize.width()));
   3611     if (features.heightSet)
   3612         windowRect.setHeight(features.height + (windowRect.height() - pageSize.height()));
   3613     page->chrome()->setWindowRect(windowRect);
   3614 
   3615     page->chrome()->show();
   3616 
   3617     created = true;
   3618     return frame;
   3619 }
   3620 
   3621 } // namespace WebCore
   3622