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