Home | History | Annotate | Download | only in loader
      1 /*
      2  * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      4  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      5  * Copyright (C) 2008 Alp Toker <alp (at) atoker.com>
      6  * Copyright (C) Research In Motion Limited 2009. All rights reserved.
      7  *
      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 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
     38 #include "Archive.h"
     39 #include "ArchiveFactory.h"
     40 #endif
     41 #include "BackForwardList.h"
     42 #include "CString.h"
     43 #include "Cache.h"
     44 #include "CachedPage.h"
     45 #include "Chrome.h"
     46 #include "DOMImplementation.h"
     47 #include "DOMWindow.h"
     48 #include "DocLoader.h"
     49 #include "Document.h"
     50 #include "DocumentLoader.h"
     51 #include "Editor.h"
     52 #include "EditorClient.h"
     53 #include "Element.h"
     54 #include "Event.h"
     55 #include "EventNames.h"
     56 #include "FloatRect.h"
     57 #include "FormState.h"
     58 #include "Frame.h"
     59 #include "FrameLoadRequest.h"
     60 #include "FrameLoaderClient.h"
     61 #include "FrameTree.h"
     62 #include "FrameView.h"
     63 #include "HTMLAnchorElement.h"
     64 #include "HTMLAppletElement.h"
     65 #include "HTMLFormElement.h"
     66 #include "HTMLFrameElement.h"
     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 "RenderPart.h"
     87 #include "RenderView.h"
     88 #include "RenderWidget.h"
     89 #include "ResourceHandle.h"
     90 #include "ResourceRequest.h"
     91 #include "ScriptController.h"
     92 #include "ScriptSourceCode.h"
     93 #include "ScriptString.h"
     94 #include "ScriptValue.h"
     95 #include "SecurityOrigin.h"
     96 #include "SegmentedString.h"
     97 #include "Settings.h"
     98 
     99 #if ENABLE(SHARED_WORKERS)
    100 #include "SharedWorkerRepository.h"
    101 #endif
    102 
    103 #include "TextResourceDecoder.h"
    104 #include "WindowFeatures.h"
    105 #include "XMLHttpRequest.h"
    106 #include "XMLTokenizer.h"
    107 #include "XSSAuditor.h"
    108 #include <wtf/CurrentTime.h>
    109 #include <wtf/StdLibExtras.h>
    110 
    111 
    112 #if ENABLE(SVG)
    113 #include "SVGDocument.h"
    114 #include "SVGLocatable.h"
    115 #include "SVGNames.h"
    116 #include "SVGPreserveAspectRatio.h"
    117 #include "SVGSVGElement.h"
    118 #include "SVGViewElement.h"
    119 #include "SVGViewSpec.h"
    120 #endif
    121 
    122 #ifdef ANDROID_INSTRUMENT
    123 #include "TimeCounter.h"
    124 #include "RenderArena.h"
    125 #endif
    126 
    127 namespace WebCore {
    128 
    129 #if ENABLE(SVG)
    130 using namespace SVGNames;
    131 #endif
    132 using namespace HTMLNames;
    133 
    134 #if ENABLE(XHTMLMP)
    135 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";
    136 #else
    137 static const char defaultAcceptHeader[] = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
    138 #endif
    139 static double storedTimeOfLastCompletedLoad;
    140 
    141 bool isBackForwardLoadType(FrameLoadType type)
    142 {
    143     switch (type) {
    144         case FrameLoadTypeStandard:
    145         case FrameLoadTypeReload:
    146         case FrameLoadTypeReloadFromOrigin:
    147         case FrameLoadTypeSame:
    148         case FrameLoadTypeRedirectWithLockedBackForwardList:
    149         case FrameLoadTypeReplace:
    150             return false;
    151         case FrameLoadTypeBack:
    152         case FrameLoadTypeBackWMLDeckNotAccessible:
    153         case FrameLoadTypeForward:
    154         case FrameLoadTypeIndexedBackForward:
    155             return true;
    156     }
    157     ASSERT_NOT_REACHED();
    158     return false;
    159 }
    160 
    161 static int numRequests(Document* document)
    162 {
    163     if (!document)
    164         return 0;
    165 
    166     return document->docLoader()->requestCount();
    167 }
    168 
    169 static inline bool canReferToParentFrameEncoding(const Frame* frame, const Frame* parentFrame)
    170 {
    171     return parentFrame && parentFrame->document()->securityOrigin()->canAccess(frame->document()->securityOrigin());
    172 }
    173 
    174 FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
    175     : m_frame(frame)
    176     , m_client(client)
    177     , m_policyChecker(frame)
    178     , m_history(frame)
    179     , m_notifer(frame)
    180     , m_state(FrameStateCommittedPage)
    181     , m_loadType(FrameLoadTypeStandard)
    182     , m_delegateIsHandlingProvisionalLoadError(false)
    183     , m_firstLayoutDone(false)
    184     , m_quickRedirectComing(false)
    185     , m_sentRedirectNotification(false)
    186     , m_inStopAllLoaders(false)
    187     , m_isExecutingJavaScriptFormAction(false)
    188     , m_didCallImplicitClose(false)
    189     , m_wasUnloadEventEmitted(false)
    190     , m_unloadEventBeingDispatched(false)
    191     , m_isComplete(false)
    192     , m_isLoadingMainResource(false)
    193     , m_needsClear(false)
    194     , m_receivedData(false)
    195     , m_encodingWasChosenByUser(false)
    196     , m_containsPlugIns(false)
    197     , m_checkTimer(this, &FrameLoader::checkTimerFired)
    198     , m_shouldCallCheckCompleted(false)
    199     , m_shouldCallCheckLoadComplete(false)
    200     , m_opener(0)
    201     , m_creatingInitialEmptyDocument(false)
    202     , m_isDisplayingInitialEmptyDocument(false)
    203     , m_committedFirstRealDocumentLoad(false)
    204     , m_didPerformFirstNavigation(false)
    205     , m_loadingFromCachedPage(false)
    206     , m_suppressOpenerInNewFrame(false)
    207     , m_sandboxFlags(SandboxAll)
    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     // this somewhat odd set of steps is needed to give the frame an initial empty document
    228     m_isDisplayingInitialEmptyDocument = false;
    229     m_creatingInitialEmptyDocument = true;
    230     setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, "")), SubstituteData()).get());
    231     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
    232     setState(FrameStateProvisional);
    233     m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String()));
    234     m_provisionalDocumentLoader->finishedLoading();
    235     begin(KURL(), false);
    236     end();
    237     m_frame->document()->cancelParsing();
    238     m_creatingInitialEmptyDocument = false;
    239     m_didCallImplicitClose = true;
    240 
    241     // Propagate sandbox attributes to this Frameloader and its descendants.
    242     updateSandboxFlags();
    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 #ifdef ANDROID_USER_GESTURE
    271                 page->chrome()->focus(isProcessingUserGesture());
    272 #else
    273                 page->chrome()->focus();
    274 #endif
    275             created = false;
    276             return frame;
    277         }
    278     }
    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 #ifdef ANDROID_USER_GESTURE
    336     request.setUserGesture(userGesture);
    337 #endif
    338 
    339     if (m_frame->script()->executeIfJavaScriptURL(request.url(), userGesture))
    340         return;
    341 
    342     urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture, SendReferrer);
    343 }
    344 
    345 void FrameLoader::urlSelected(const ResourceRequest& request, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture, ReferrerPolicy referrerPolicy)
    346 {
    347     ASSERT(!m_suppressOpenerInNewFrame);
    348 
    349     if (m_frame->script()->executeIfJavaScriptURL(request.url(), userGesture, false))
    350         return;
    351 
    352     String target = passedTarget;
    353     if (target.isEmpty())
    354         target = m_frame->document()->baseTarget();
    355 
    356     FrameLoadRequest frameRequest(request, target);
    357 
    358     if (referrerPolicy == NoReferrer)
    359         m_suppressOpenerInNewFrame = true;
    360     else if (frameRequest.resourceRequest().httpReferrer().isEmpty())
    361         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
    362     addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
    363 
    364     loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0, referrerPolicy);
    365 
    366     m_suppressOpenerInNewFrame = false;
    367 }
    368 
    369 bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName)
    370 {
    371     // Support for <frame src="javascript:string">
    372     KURL scriptURL;
    373     KURL url;
    374     if (protocolIsJavaScript(urlString)) {
    375         scriptURL = completeURL(urlString); // completeURL() encodes the URL.
    376         url = blankURL();
    377     } else
    378         url = completeURL(urlString);
    379 
    380     Frame* frame = ownerElement->contentFrame();
    381     if (frame)
    382         frame->redirectScheduler()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, isProcessingUserGesture());
    383     else
    384         frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer);
    385 
    386     if (!frame)
    387         return false;
    388 
    389     if (!scriptURL.isEmpty())
    390         frame->script()->executeIfJavaScriptURL(scriptURL);
    391 
    392     return true;
    393 }
    394 
    395 Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL& url, const String& name, const String& referrer)
    396 {
    397     bool allowsScrolling = true;
    398     int marginWidth = -1;
    399     int marginHeight = -1;
    400     if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
    401         HTMLFrameElementBase* o = static_cast<HTMLFrameElementBase*>(ownerElement);
    402         allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff;
    403         marginWidth = o->getMarginWidth();
    404         marginHeight = o->getMarginHeight();
    405     }
    406 
    407     if (!SecurityOrigin::canLoad(url, referrer, 0)) {
    408         FrameLoader::reportLocalLoadFailed(m_frame, url.string());
    409         return 0;
    410     }
    411 
    412     bool hideReferrer = SecurityOrigin::shouldHideReferrer(url, referrer);
    413     RefPtr<Frame> frame = m_client->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer, allowsScrolling, marginWidth, marginHeight);
    414 
    415     if (!frame)  {
    416         checkCallImplicitClose();
    417         return 0;
    418     }
    419 
    420     // All new frames will have m_isComplete set to true at this point due to synchronously loading
    421     // an empty document in FrameLoader::init(). But many frames will now be starting an
    422     // asynchronous load of url, so we set m_isComplete to false and then check if the load is
    423     // actually completed below. (Note that we set m_isComplete to false even for synchronous
    424     // loads, so that checkCompleted() below won't bail early.)
    425     // FIXME: Can we remove this entirely? m_isComplete normally gets set to false when a load is committed.
    426     frame->loader()->m_isComplete = false;
    427 
    428     RenderObject* renderer = ownerElement->renderer();
    429     FrameView* view = frame->view();
    430     if (renderer && renderer->isWidget() && view)
    431         toRenderWidget(renderer)->setWidget(view);
    432 
    433     checkCallImplicitClose();
    434 
    435     // Some loads are performed synchronously (e.g., about:blank and loads
    436     // cancelled by returning a null ResourceRequest from requestFromDelegate).
    437     // In these cases, the synchronous load would have finished
    438     // before we could connect the signals, so make sure to send the
    439     // completed() signal for the child by hand and mark the load as being
    440     // complete.
    441     // FIXME: In this case the Frame will have finished loading before
    442     // it's being added to the child list. It would be a good idea to
    443     // create the child first, then invoke the loader separately.
    444     if (frame->loader()->state() == FrameStateComplete)
    445         frame->loader()->checkCompleted();
    446 
    447     return frame.get();
    448 }
    449 
    450 void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData,
    451     const String& target, const String& contentType, const String& boundary,
    452     bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
    453 {
    454     ASSERT(action);
    455     ASSERT(strcmp(action, "GET") == 0 || strcmp(action, "POST") == 0);
    456     ASSERT(formData);
    457     ASSERT(formState);
    458     ASSERT(formState->sourceFrame() == m_frame);
    459 
    460     if (!m_frame->page())
    461         return;
    462 
    463     KURL u = completeURL(url.isNull() ? "" : url);
    464     if (u.isEmpty())
    465         return;
    466 
    467     if (isDocumentSandboxed(SandboxForms))
    468         return;
    469 
    470     if (protocolIsJavaScript(u)) {
    471         m_isExecutingJavaScriptFormAction = true;
    472         m_frame->script()->executeIfJavaScriptURL(u, false, false);
    473         m_isExecutingJavaScriptFormAction = false;
    474         return;
    475     }
    476 
    477     FrameLoadRequest frameRequest;
    478 #ifdef ANDROID_USER_GESTURE
    479     frameRequest.resourceRequest().setUserGesture(isProcessingUserGesture());
    480 #endif
    481 
    482     String targetOrBaseTarget = target.isEmpty() ? m_frame->document()->baseTarget() : target;
    483     Frame* targetFrame = findFrameForNavigation(targetOrBaseTarget);
    484     if (!targetFrame) {
    485         targetFrame = m_frame;
    486         frameRequest.setFrameName(targetOrBaseTarget);
    487     }
    488     if (!targetFrame->page())
    489         return;
    490 
    491     // FIXME: We'd like to remove this altogether and fix the multiple form submission issue another way.
    492 
    493     // We do not want to submit more than one form from the same page, nor do we want to submit a single
    494     // form more than once. This flag prevents these from happening; not sure how other browsers prevent this.
    495     // The flag is reset in each time we start handle a new mouse or key down event, and
    496     // also in setView since this part may get reused for a page from the back/forward cache.
    497     // The form multi-submit logic here is only needed when we are submitting a form that affects this frame.
    498 
    499     // FIXME: Frame targeting is only one of the ways the submission could end up doing something other
    500     // than replacing this frame's content, so this check is flawed. On the other hand, the check is hardly
    501     // needed any more now that we reset m_submittedFormURL on each mouse or key down event.
    502 
    503     if (m_frame->tree()->isDescendantOf(targetFrame)) {
    504         if (m_submittedFormURL == u)
    505             return;
    506         m_submittedFormURL = u;
    507     }
    508 
    509     formData->generateFiles(m_frame->page()->chrome()->client());
    510 
    511     if (!m_outgoingReferrer.isEmpty())
    512         frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer);
    513 
    514     if (strcmp(action, "GET") == 0)
    515         u.setQuery(formData->flattenToString());
    516     else {
    517         frameRequest.resourceRequest().setHTTPMethod("POST");
    518         frameRequest.resourceRequest().setHTTPBody(formData);
    519 
    520         // construct some user headers if necessary
    521         if (contentType.isNull() || contentType == "application/x-www-form-urlencoded")
    522             frameRequest.resourceRequest().setHTTPContentType(contentType);
    523         else // contentType must be "multipart/form-data"
    524             frameRequest.resourceRequest().setHTTPContentType(contentType + "; boundary=" + boundary);
    525     }
    526 
    527     frameRequest.resourceRequest().setURL(u);
    528     addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
    529 
    530     targetFrame->redirectScheduler()->scheduleFormSubmission(frameRequest, lockHistory, event, formState);
    531 }
    532 
    533 void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolicy databasePolicy)
    534 {
    535     if (m_frame->document() && m_frame->document()->tokenizer())
    536         m_frame->document()->tokenizer()->stopParsing();
    537 
    538     if (unloadEventPolicy != UnloadEventPolicyNone) {
    539         if (m_frame->document()) {
    540             if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
    541                 Node* currentFocusedNode = m_frame->document()->focusedNode();
    542                 if (currentFocusedNode)
    543                     currentFocusedNode->aboutToUnload();
    544                 m_unloadEventBeingDispatched = true;
    545                 if (m_frame->domWindow()) {
    546                     if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide)
    547                         m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document());
    548                     if (!m_frame->document()->inPageCache())
    549                         m_frame->domWindow()->dispatchEvent(Event::create(eventNames().unloadEvent, false, false), m_frame->domWindow()->document());
    550                 }
    551                 m_unloadEventBeingDispatched = false;
    552                 if (m_frame->document())
    553                     m_frame->document()->updateStyleIfNeeded();
    554                 m_wasUnloadEventEmitted = true;
    555             }
    556         }
    557 
    558         // Dispatching the unload event could have made m_frame->document() null.
    559         if (m_frame->document() && !m_frame->document()->inPageCache()) {
    560             // Don't remove event listeners from a transitional empty document (see bug 28716 for more information).
    561             bool keepEventListeners = m_isDisplayingInitialEmptyDocument && m_provisionalDocumentLoader
    562                 && m_frame->document()->securityOrigin()->isSecureTransitionTo(m_provisionalDocumentLoader->url());
    563 
    564             if (!keepEventListeners)
    565                 m_frame->document()->removeAllEventListeners();
    566         }
    567     }
    568 
    569     m_isComplete = true; // to avoid calling completed() in finishedParsing()
    570     m_isLoadingMainResource = false;
    571     m_didCallImplicitClose = true; // don't want that one either
    572 
    573     if (m_frame->document() && m_frame->document()->parsing()) {
    574         finishedParsing();
    575         m_frame->document()->setParsing(false);
    576     }
    577 
    578     m_workingURL = KURL();
    579 
    580     if (Document* doc = m_frame->document()) {
    581         if (DocLoader* docLoader = doc->docLoader())
    582             cache()->loader()->cancelRequests(docLoader);
    583 
    584 #if ENABLE(DATABASE)
    585         if (databasePolicy == DatabasePolicyStop)
    586             doc->stopDatabases(0);
    587 #else
    588     UNUSED_PARAM(databasePolicy);
    589 #endif
    590     }
    591 
    592     // tell all subframes to stop as well
    593     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
    594         child->loader()->stopLoading(unloadEventPolicy);
    595 
    596     m_frame->redirectScheduler()->cancel();
    597 }
    598 
    599 void FrameLoader::stop()
    600 {
    601     // http://bugs.webkit.org/show_bug.cgi?id=10854
    602     // The frame's last ref may be removed and it will be deleted by checkCompleted().
    603     RefPtr<Frame> protector(m_frame);
    604 
    605     if (m_frame->document()->tokenizer())
    606         m_frame->document()->tokenizer()->stopParsing();
    607     m_frame->document()->finishParsing();
    608 
    609     if (m_iconLoader)
    610         m_iconLoader->stopLoading();
    611 }
    612 
    613 bool FrameLoader::closeURL()
    614 {
    615     history()->saveDocumentState();
    616 
    617     // Should only send the pagehide event here if the current document exists and has not been placed in the page cache.
    618     Document* currentDocument = m_frame->document();
    619     stopLoading(currentDocument && !currentDocument->inPageCache() ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly);
    620 
    621     m_frame->editor()->clearUndoRedoOperations();
    622     return true;
    623 }
    624 
    625 KURL FrameLoader::iconURL()
    626 {
    627     // If this isn't a top level frame, return nothing
    628     if (m_frame->tree() && m_frame->tree()->parent())
    629         return KURL();
    630 
    631     // If we have an iconURL from a Link element, return that
    632     if (!m_frame->document()->iconURL().isEmpty())
    633         return KURL(ParsedURLString, m_frame->document()->iconURL());
    634 
    635     // Don't return a favicon iconURL unless we're http or https
    636     if (!m_URL.protocolInHTTPFamily())
    637         return KURL();
    638 
    639     KURL url;
    640     bool couldSetProtocol = url.setProtocol(m_URL.protocol());
    641     ASSERT_UNUSED(couldSetProtocol, couldSetProtocol);
    642     url.setHost(m_URL.host());
    643     if (m_URL.hasPort())
    644         url.setPort(m_URL.port());
    645     url.setPath("/favicon.ico");
    646     return url;
    647 }
    648 
    649 bool FrameLoader::didOpenURL(const KURL& url)
    650 {
    651     if (m_frame->redirectScheduler()->redirectScheduledDuringLoad()) {
    652         // A redirect was scheduled before the document was created.
    653         // This can happen when one frame changes another frame's location.
    654         return false;
    655     }
    656 
    657     m_frame->redirectScheduler()->cancel();
    658     m_frame->editor()->clearLastEditCommand();
    659 
    660     m_isComplete = false;
    661     m_isLoadingMainResource = true;
    662     m_didCallImplicitClose = false;
    663 
    664     // If we are still in the process of initializing an empty document then
    665     // its frame is not in a consistent state for rendering, so avoid setJSStatusBarText
    666     // since it may cause clients to attempt to render the frame.
    667     if (!m_creatingInitialEmptyDocument) {
    668         m_frame->setJSStatusBarText(String());
    669         m_frame->setJSDefaultStatusBarText(String());
    670     }
    671     m_URL = url;
    672     if (m_URL.protocolInHTTPFamily() && !m_URL.host().isEmpty() && m_URL.path().isEmpty())
    673         m_URL.setPath("/");
    674     m_workingURL = m_URL;
    675 
    676     started();
    677 
    678     return true;
    679 }
    680 
    681 void FrameLoader::didExplicitOpen()
    682 {
    683     m_isComplete = false;
    684     m_didCallImplicitClose = false;
    685 
    686     // Calling document.open counts as committing the first real document load.
    687     m_committedFirstRealDocumentLoad = true;
    688 
    689     // Prevent window.open(url) -- eg window.open("about:blank") -- from blowing away results
    690     // from a subsequent window.document.open / window.document.write call.
    691     // Canceling redirection here works for all cases because document.open
    692     // implicitly precedes document.write.
    693     m_frame->redirectScheduler()->cancel();
    694     if (m_frame->document()->url() != blankURL())
    695         m_URL = m_frame->document()->url();
    696 }
    697 
    698 
    699 void FrameLoader::cancelAndClear()
    700 {
    701     m_frame->redirectScheduler()->cancel();
    702 
    703     if (!m_isComplete)
    704         closeURL();
    705 
    706     clear(false);
    707     m_frame->script()->updatePlatformScriptObjects();
    708 }
    709 
    710 void FrameLoader::replaceDocument(const String& html)
    711 {
    712     stopAllLoaders();
    713     begin(m_URL, true, m_frame->document()->securityOrigin());
    714     write(html);
    715     end();
    716 }
    717 
    718 void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView)
    719 {
    720     m_frame->editor()->clear();
    721 
    722     if (!m_needsClear)
    723         return;
    724     m_needsClear = false;
    725 
    726     if (!m_frame->document()->inPageCache()) {
    727         m_frame->document()->cancelParsing();
    728         m_frame->document()->stopActiveDOMObjects();
    729         if (m_frame->document()->attached()) {
    730             m_frame->document()->willRemove();
    731             m_frame->document()->detach();
    732 
    733             m_frame->document()->removeFocusedNodeOfSubtree(m_frame->document());
    734         }
    735     }
    736 
    737     // Do this after detaching the document so that the unload event works.
    738     if (clearWindowProperties) {
    739         m_frame->clearDOMWindow();
    740         m_frame->script()->clearWindowShell();
    741     }
    742 
    743     m_frame->selection()->clear();
    744     m_frame->eventHandler()->clear();
    745     if (clearFrameView && m_frame->view())
    746         m_frame->view()->clear();
    747 
    748     m_frame->setSelectionGranularity(CharacterGranularity);
    749 
    750     // Do not drop the document before the ScriptController and view are cleared
    751     // as some destructors might still try to access the document.
    752     m_frame->setDocument(0);
    753     m_decoder = 0;
    754 
    755     m_containsPlugIns = false;
    756 
    757     if (clearScriptObjects)
    758         m_frame->script()->clearScriptObjects();
    759 
    760     m_frame->redirectScheduler()->clear();
    761 
    762     m_checkTimer.stop();
    763     m_shouldCallCheckCompleted = false;
    764     m_shouldCallCheckLoadComplete = false;
    765 
    766     m_receivedData = false;
    767     m_isDisplayingInitialEmptyDocument = false;
    768 
    769     if (!m_encodingWasChosenByUser)
    770         m_encoding = String();
    771 }
    772 
    773 void FrameLoader::receivedFirstData()
    774 {
    775     begin(m_workingURL, false);
    776 
    777     dispatchDidCommitLoad();
    778     dispatchDidClearWindowObjectsInAllWorlds();
    779 
    780     if (m_documentLoader) {
    781         String ptitle = m_documentLoader->title();
    782         // If we have a title let the WebView know about it.
    783         if (!ptitle.isNull())
    784             m_client->dispatchDidReceiveTitle(ptitle);
    785     }
    786 
    787     m_workingURL = KURL();
    788 
    789     double delay;
    790     String url;
    791     if (!m_documentLoader)
    792         return;
    793     if (m_frame->inViewSourceMode())
    794         return;
    795     if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField("Refresh"), false, delay, url))
    796         return;
    797 
    798     if (url.isEmpty())
    799         url = m_URL.string();
    800     else
    801         url = m_frame->document()->completeURL(url).string();
    802 
    803     m_frame->redirectScheduler()->scheduleRedirect(delay, url);
    804 }
    805 
    806 const String& FrameLoader::responseMIMEType() const
    807 {
    808     return m_responseMIMEType;
    809 }
    810 
    811 void FrameLoader::setResponseMIMEType(const String& type)
    812 {
    813     m_responseMIMEType = type;
    814 }
    815 
    816 void FrameLoader::begin()
    817 {
    818     begin(KURL());
    819 }
    820 
    821 void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
    822 {
    823     // We need to take a reference to the security origin because |clear|
    824     // might destroy the document that owns it.
    825     RefPtr<SecurityOrigin> forcedSecurityOrigin = origin;
    826 
    827     RefPtr<Document> document;
    828 
    829     // Create a new document before clearing the frame, because it may need to inherit an aliased security context.
    830     if (!m_isDisplayingInitialEmptyDocument && m_client->shouldUsePluginDocument(m_responseMIMEType))
    831         document = PluginDocument::create(m_frame);
    832     else if (!m_client->hasHTMLView())
    833         document = PlaceholderDocument::create(m_frame);
    834     else
    835         document = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode());
    836 
    837     bool resetScripting = !(m_isDisplayingInitialEmptyDocument && m_frame->document()->securityOrigin()->isSecureTransitionTo(url));
    838     clear(resetScripting, resetScripting);
    839     if (resetScripting)
    840         m_frame->script()->updatePlatformScriptObjects();
    841 
    842     m_needsClear = true;
    843     m_isComplete = false;
    844     m_didCallImplicitClose = false;
    845     m_isLoadingMainResource = true;
    846     m_isDisplayingInitialEmptyDocument = m_creatingInitialEmptyDocument;
    847 
    848     KURL ref(url);
    849     ref.setUser(String());
    850     ref.setPass(String());
    851     ref.removeFragmentIdentifier();
    852     m_outgoingReferrer = ref.string();
    853     m_URL = url;
    854 
    855     document->setURL(m_URL);
    856     m_frame->setDocument(document);
    857 
    858     if (m_pendingStateObject) {
    859         document->statePopped(m_pendingStateObject.get());
    860         m_pendingStateObject.clear();
    861     }
    862 
    863     if (m_decoder)
    864         document->setDecoder(m_decoder.get());
    865     if (forcedSecurityOrigin)
    866         document->setSecurityOrigin(forcedSecurityOrigin.get());
    867 
    868     m_frame->domWindow()->setURL(document->url());
    869     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
    870 
    871     if (dispatch)
    872         dispatchDidClearWindowObjectsInAllWorlds();
    873 
    874     updateFirstPartyForCookies();
    875 
    876     Settings* settings = document->settings();
    877     document->docLoader()->setAutoLoadImages(settings && settings->loadsImagesAutomatically());
    878 #ifdef ANDROID_BLOCK_NETWORK_IMAGE
    879     document->docLoader()->setBlockNetworkImage(settings && settings->blockNetworkImage());
    880 #endif
    881 
    882     if (m_documentLoader) {
    883         String dnsPrefetchControl = m_documentLoader->response().httpHeaderField("X-DNS-Prefetch-Control");
    884         if (!dnsPrefetchControl.isEmpty())
    885             document->parseDNSPrefetchControlHeader(dnsPrefetchControl);
    886     }
    887 
    888     history()->restoreDocumentState();
    889 
    890     document->implicitOpen();
    891 
    892     if (m_frame->view() && m_client->hasHTMLView())
    893         m_frame->view()->setContentsSize(IntSize());
    894 }
    895 
    896 void FrameLoader::write(const char* str, int len, bool flush)
    897 {
    898     if (len == 0 && !flush)
    899         return;
    900 
    901     if (len == -1)
    902         len = strlen(str);
    903 
    904     Tokenizer* tokenizer = m_frame->document()->tokenizer();
    905     if (tokenizer && tokenizer->wantsRawData()) {
    906         if (len > 0)
    907             tokenizer->writeRawData(str, len);
    908         return;
    909     }
    910 
    911     if (!m_decoder) {
    912         if (Settings* settings = m_frame->settings()) {
    913             m_decoder = TextResourceDecoder::create(m_responseMIMEType,
    914                 settings->defaultTextEncodingName(),
    915                 settings->usesEncodingDetector());
    916             Frame* parentFrame = m_frame->tree()->parent();
    917             // Set the hint encoding to the parent frame encoding only if
    918             // the parent and the current frames share the security origin.
    919             // We impose this condition because somebody can make a child frame
    920             // containing a carefully crafted html/javascript in one encoding
    921             // that can be mistaken for hintEncoding (or related encoding) by
    922             // an auto detector. When interpreted in the latter, it could be
    923             // an attack vector.
    924             // FIXME: This might be too cautious for non-7bit-encodings and
    925             // we may consider relaxing this later after testing.
    926             if (canReferToParentFrameEncoding(m_frame, parentFrame))
    927                 m_decoder->setHintEncoding(parentFrame->document()->decoder());
    928         } else
    929             m_decoder = TextResourceDecoder::create(m_responseMIMEType, String());
    930         Frame* parentFrame = m_frame->tree()->parent();
    931         if (m_encoding.isEmpty()) {
    932             if (canReferToParentFrameEncoding(m_frame, parentFrame))
    933                 m_decoder->setEncoding(parentFrame->document()->inputEncoding(), TextResourceDecoder::EncodingFromParentFrame);
    934         } else {
    935             m_decoder->setEncoding(m_encoding,
    936                 m_encodingWasChosenByUser ? TextResourceDecoder::UserChosenEncoding : TextResourceDecoder::EncodingFromHTTPHeader);
    937         }
    938         m_frame->document()->setDecoder(m_decoder.get());
    939     }
    940 
    941     String decoded = m_decoder->decode(str, len);
    942     if (flush)
    943         decoded += m_decoder->flush();
    944     if (decoded.isEmpty())
    945         return;
    946 
    947     if (!m_receivedData) {
    948         m_receivedData = true;
    949         if (m_decoder->encoding().usesVisualOrdering())
    950             m_frame->document()->setVisuallyOrdered();
    951         m_frame->document()->recalcStyle(Node::Force);
    952     }
    953 
    954     if (tokenizer) {
    955         ASSERT(!tokenizer->wantsRawData());
    956         tokenizer->write(decoded, true);
    957     }
    958 }
    959 
    960 void FrameLoader::write(const String& str)
    961 {
    962     if (str.isNull())
    963         return;
    964 
    965     if (!m_receivedData) {
    966         m_receivedData = true;
    967         m_frame->document()->setParseMode(Document::Strict);
    968     }
    969 
    970     if (Tokenizer* tokenizer = m_frame->document()->tokenizer())
    971         tokenizer->write(str, true);
    972 }
    973 
    974 void FrameLoader::end()
    975 {
    976     m_isLoadingMainResource = false;
    977     endIfNotLoadingMainResource();
    978 }
    979 
    980 void FrameLoader::endIfNotLoadingMainResource()
    981 {
    982     if (m_isLoadingMainResource || !m_frame->page() || !m_frame->document())
    983         return;
    984 
    985     // http://bugs.webkit.org/show_bug.cgi?id=10854
    986     // The frame's last ref may be removed and it can be deleted by checkCompleted(),
    987     // so we'll add a protective refcount
    988     RefPtr<Frame> protector(m_frame);
    989 
    990     // make sure nothing's left in there
    991     write(0, 0, true);
    992     m_frame->document()->finishParsing();
    993 }
    994 
    995 void FrameLoader::iconLoadDecisionAvailable()
    996 {
    997     if (!m_mayLoadIconLater)
    998         return;
    999     LOG(IconDatabase, "FrameLoader %p was told a load decision is available for its icon", this);
   1000     startIconLoader();
   1001     m_mayLoadIconLater = false;
   1002 }
   1003 
   1004 void FrameLoader::startIconLoader()
   1005 {
   1006     // FIXME: We kick off the icon loader when the frame is done receiving its main resource.
   1007     // But we should instead do it when we're done parsing the head element.
   1008     if (!isLoadingMainFrame())
   1009         return;
   1010 
   1011     if (!iconDatabase() || !iconDatabase()->isEnabled())
   1012         return;
   1013 
   1014     KURL url(iconURL());
   1015     String urlString(url.string());
   1016     if (urlString.isEmpty())
   1017         return;
   1018 
   1019     // If we're not reloading and the icon database doesn't say to load now then bail before we actually start the load
   1020     if (loadType() != FrameLoadTypeReload && loadType() != FrameLoadTypeReloadFromOrigin) {
   1021         IconLoadDecision decision = iconDatabase()->loadDecisionForIconURL(urlString, m_documentLoader.get());
   1022         if (decision == IconLoadNo) {
   1023             LOG(IconDatabase, "FrameLoader::startIconLoader() - Told not to load this icon, committing iconURL %s to database for pageURL mapping", urlString.ascii().data());
   1024             commitIconURLToIconDatabase(url);
   1025 
   1026             // We were told not to load this icon - that means this icon is already known by the database
   1027             // 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
   1028             // has done it.  This is after registering for the notification so the WebView can call the appropriate delegate method.
   1029             // Otherwise if the icon data *is* available, notify the delegate
   1030             if (!iconDatabase()->iconDataKnownForIconURL(urlString)) {
   1031                 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());
   1032                 m_client->registerForIconNotification();
   1033                 iconDatabase()->iconForPageURL(m_URL.string(), IntSize(0, 0));
   1034                 iconDatabase()->iconForPageURL(originalRequestURL().string(), IntSize(0, 0));
   1035             } else
   1036                 m_client->dispatchDidReceiveIcon();
   1037 
   1038             return;
   1039         }
   1040 
   1041         if (decision == IconLoadUnknown) {
   1042             // In this case, we may end up loading the icon later, but we still want to commit the icon url mapping to the database
   1043             // 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
   1044             // We also tell the client to register for the notification that the icon is received now so it isn't missed in case the
   1045             // icon is later read in from disk
   1046             LOG(IconDatabase, "FrameLoader %p might load icon %s later", this, urlString.ascii().data());
   1047             m_mayLoadIconLater = true;
   1048             m_client->registerForIconNotification();
   1049             commitIconURLToIconDatabase(url);
   1050             return;
   1051         }
   1052     }
   1053 
   1054     // People who want to avoid loading images generally want to avoid loading all images.
   1055     // Now that we've accounted for URL mapping, avoid starting the network load if images aren't set to display automatically.
   1056     Settings* settings = m_frame->settings();
   1057     if (settings && !settings->loadsImagesAutomatically())
   1058         return;
   1059 
   1060     // This is either a reload or the icon database said "yes, load the icon", so kick off the load!
   1061     if (!m_iconLoader)
   1062         m_iconLoader.set(IconLoader::create(m_frame).release());
   1063 
   1064     m_iconLoader->startLoading();
   1065 }
   1066 
   1067 void FrameLoader::commitIconURLToIconDatabase(const KURL& icon)
   1068 {
   1069     ASSERT(iconDatabase());
   1070     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());
   1071     iconDatabase()->setIconURLForPageURL(icon.string(), m_URL.string());
   1072     iconDatabase()->setIconURLForPageURL(icon.string(), originalRequestURL().string());
   1073 }
   1074 
   1075 void FrameLoader::finishedParsing()
   1076 {
   1077     if (m_creatingInitialEmptyDocument)
   1078         return;
   1079 
   1080     m_frame->injectUserScripts(InjectAtDocumentEnd);
   1081 
   1082     // This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
   1083     // because doing so will cause us to re-enter the destructor when protector goes out of scope.
   1084     // Null-checking the FrameView indicates whether or not we're in the destructor.
   1085     RefPtr<Frame> protector = m_frame->view() ? m_frame : 0;
   1086 
   1087     m_client->dispatchDidFinishDocumentLoad();
   1088 
   1089     checkCompleted();
   1090 
   1091     if (!m_frame->view())
   1092         return; // We are being destroyed by something checkCompleted called.
   1093 
   1094     // Check if the scrollbars are really needed for the content.
   1095     // If not, remove them, relayout, and repaint.
   1096     m_frame->view()->restoreScrollbar();
   1097     m_frame->view()->scrollToFragment(m_URL);
   1098 }
   1099 
   1100 void FrameLoader::loadDone()
   1101 {
   1102     checkCompleted();
   1103 }
   1104 
   1105 bool FrameLoader::allChildrenAreComplete() const
   1106 {
   1107     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
   1108         if (!child->loader()->m_isComplete)
   1109             return false;
   1110     }
   1111     return true;
   1112 }
   1113 
   1114 bool FrameLoader::allAncestorsAreComplete() const
   1115 {
   1116     for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) {
   1117         if (!ancestor->loader()->m_isComplete)
   1118             return false;
   1119     }
   1120     return true;
   1121 }
   1122 
   1123 void FrameLoader::checkCompleted()
   1124 {
   1125     m_shouldCallCheckCompleted = false;
   1126 
   1127     if (m_frame->view())
   1128         m_frame->view()->checkStopDelayingDeferredRepaints();
   1129 
   1130     // Any frame that hasn't completed yet?
   1131     if (!allChildrenAreComplete())
   1132         return;
   1133 
   1134     // Have we completed before?
   1135     if (m_isComplete)
   1136         return;
   1137 
   1138     // Are we still parsing?
   1139     if (m_frame->document()->parsing())
   1140         return;
   1141 
   1142     // Still waiting for images/scripts?
   1143     if (numRequests(m_frame->document()))
   1144         return;
   1145 
   1146     // OK, completed.
   1147     m_isComplete = true;
   1148 
   1149     RefPtr<Frame> protect(m_frame);
   1150     checkCallImplicitClose(); // if we didn't do it before
   1151 
   1152     m_frame->redirectScheduler()->startTimer();
   1153 
   1154     completed();
   1155     if (m_frame->page())
   1156         checkLoadComplete();
   1157 }
   1158 
   1159 void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
   1160 {
   1161     if (Page* page = m_frame->page()) {
   1162         if (page->defersLoading())
   1163             return;
   1164     }
   1165     if (m_shouldCallCheckCompleted)
   1166         checkCompleted();
   1167     if (m_shouldCallCheckLoadComplete)
   1168         checkLoadComplete();
   1169 }
   1170 
   1171 void FrameLoader::startCheckCompleteTimer()
   1172 {
   1173     if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
   1174         return;
   1175     if (m_checkTimer.isActive())
   1176         return;
   1177     m_checkTimer.startOneShot(0);
   1178 }
   1179 
   1180 void FrameLoader::scheduleCheckCompleted()
   1181 {
   1182     m_shouldCallCheckCompleted = true;
   1183     startCheckCompleteTimer();
   1184 }
   1185 
   1186 void FrameLoader::scheduleCheckLoadComplete()
   1187 {
   1188     m_shouldCallCheckLoadComplete = true;
   1189     startCheckCompleteTimer();
   1190 }
   1191 
   1192 void FrameLoader::checkCallImplicitClose()
   1193 {
   1194     if (m_didCallImplicitClose || m_frame->document()->parsing())
   1195         return;
   1196 
   1197     if (!allChildrenAreComplete())
   1198         return; // still got a frame running -> too early
   1199 
   1200     m_didCallImplicitClose = true;
   1201     m_wasUnloadEventEmitted = false;
   1202     m_frame->document()->implicitClose();
   1203 }
   1204 
   1205 KURL FrameLoader::baseURL() const
   1206 {
   1207     ASSERT(m_frame->document());
   1208     return m_frame->document()->baseURL();
   1209 }
   1210 
   1211 KURL FrameLoader::completeURL(const String& url)
   1212 {
   1213     ASSERT(m_frame->document());
   1214     return m_frame->document()->completeURL(url);
   1215 }
   1216 
   1217 void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
   1218 {
   1219     ASSERT(childFrame);
   1220 
   1221     HistoryItem* parentItem = history()->currentItem();
   1222     FrameLoadType loadType = this->loadType();
   1223     FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList;
   1224 
   1225     KURL workingURL = url;
   1226 
   1227     // If we're moving in the back/forward list, we might want to replace the content
   1228     // of this child frame with whatever was there at that point.
   1229     if (parentItem && parentItem->children().size() && isBackForwardLoadType(loadType)) {
   1230         HistoryItem* childItem = parentItem->childItemWithTarget(childFrame->tree()->name());
   1231         if (childItem) {
   1232             // Use the original URL to ensure we get all the side-effects, such as
   1233             // onLoad handlers, of any redirects that happened. An example of where
   1234             // this is needed is Radar 3213556.
   1235             workingURL = KURL(ParsedURLString, childItem->originalURLString());
   1236             childLoadType = loadType;
   1237             childFrame->loader()->history()->setProvisionalItem(childItem);
   1238         }
   1239     }
   1240 
   1241 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
   1242     RefPtr<Archive> subframeArchive = activeDocumentLoader()->popArchiveForSubframe(childFrame->tree()->name());
   1243 
   1244     if (subframeArchive)
   1245         childFrame->loader()->loadArchive(subframeArchive.release());
   1246     else
   1247 #endif
   1248 #ifdef ANDROID_USER_GESTURE
   1249         childFrame->loader()->loadURL(workingURL, referer, String(), false, childLoadType, 0, 0, false);
   1250 #else
   1251         childFrame->loader()->loadURL(workingURL, referer, String(), false, childLoadType, 0, 0);
   1252 #endif
   1253 }
   1254 
   1255 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
   1256 void FrameLoader::loadArchive(PassRefPtr<Archive> prpArchive)
   1257 {
   1258     RefPtr<Archive> archive = prpArchive;
   1259 
   1260     ArchiveResource* mainResource = archive->mainResource();
   1261     ASSERT(mainResource);
   1262     if (!mainResource)
   1263         return;
   1264 
   1265     SubstituteData substituteData(mainResource->data(), mainResource->mimeType(), mainResource->textEncoding(), KURL());
   1266 
   1267     ResourceRequest request(mainResource->url());
   1268 #if PLATFORM(MAC)
   1269     request.applyWebArchiveHackForMail();
   1270 #endif
   1271 
   1272     RefPtr<DocumentLoader> documentLoader = m_client->createDocumentLoader(request, substituteData);
   1273     documentLoader->addAllArchiveResources(archive.get());
   1274     load(documentLoader.get());
   1275 }
   1276 #endif
   1277 
   1278 String FrameLoader::encoding() const
   1279 {
   1280     if (m_encodingWasChosenByUser && !m_encoding.isEmpty())
   1281         return m_encoding;
   1282     if (m_decoder && m_decoder->encoding().isValid())
   1283         return m_decoder->encoding().name();
   1284     Settings* settings = m_frame->settings();
   1285     return settings ? settings->defaultTextEncodingName() : String();
   1286 }
   1287 
   1288 bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName,
   1289     const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues)
   1290 {
   1291     if (url.isEmpty() && mimeType.isEmpty())
   1292         return false;
   1293 
   1294     if (!m_frame->script()->xssAuditor()->canLoadObject(url)) {
   1295         // It is unsafe to honor the request for this object.
   1296         return false;
   1297     }
   1298 
   1299     KURL completedURL;
   1300     if (!url.isEmpty())
   1301         completedURL = completeURL(url);
   1302 
   1303     bool useFallback;
   1304     if (shouldUsePlugin(completedURL, mimeType, renderer->hasFallbackContent(), useFallback)) {
   1305         Settings* settings = m_frame->settings();
   1306         if (!m_client->allowPlugins(settings && settings->arePluginsEnabled())
   1307             || (!settings->isJavaEnabled() && MIMETypeRegistry::isJavaAppletMIMEType(mimeType)))
   1308             return false;
   1309         if (isDocumentSandboxed(SandboxPlugins))
   1310             return false;
   1311         return loadPlugin(renderer, completedURL, mimeType, paramNames, paramValues, useFallback);
   1312     }
   1313 
   1314     ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
   1315     HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node());
   1316 
   1317     // If the plug-in element already contains a subframe, requestFrame will re-use it. Otherwise,
   1318     // it will create a new frame and set it as the RenderPart's widget, causing what was previously
   1319     // in the widget to be torn down.
   1320     return requestFrame(element, completedURL, frameName);
   1321 }
   1322 
   1323 bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
   1324 {
   1325     if (m_client->shouldUsePluginDocument(mimeType)) {
   1326         useFallback = false;
   1327         return true;
   1328     }
   1329 
   1330     // Allow other plug-ins to win over QuickTime because if the user has installed a plug-in that
   1331     // can handle TIFF (which QuickTime can also handle) they probably intended to override QT.
   1332     if (m_frame->page() && (mimeType == "image/tiff" || mimeType == "image/tif" || mimeType == "image/x-tiff")) {
   1333         const PluginData* pluginData = m_frame->page()->pluginData();
   1334         String pluginName = pluginData ? pluginData->pluginNameForMimeType(mimeType) : String();
   1335         if (!pluginName.isEmpty() && !pluginName.contains("QuickTime", false))
   1336             return true;
   1337     }
   1338 
   1339     ObjectContentType objectType = m_client->objectContentType(url, mimeType);
   1340     // If an object's content can't be handled and it has no fallback, let
   1341     // it be handled as a plugin to show the broken plugin icon.
   1342     useFallback = objectType == ObjectContentNone && hasFallback;
   1343     return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin;
   1344 }
   1345 
   1346 ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn)
   1347 {
   1348     String mimeType = mimeTypeIn;
   1349     // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure
   1350     if (mimeType.isEmpty())
   1351         mimeType = MIMETypeRegistry::getMIMETypeForExtension(url.path().substring(url.path().reverseFind('.') + 1));
   1352 
   1353     if (mimeType.isEmpty())
   1354         return ObjectContentFrame; // Go ahead and hope that we can display the content.
   1355 
   1356     if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
   1357         return WebCore::ObjectContentImage;
   1358 
   1359 #if !PLATFORM(MAC) && !PLATFORM(CHROMIUM)  // Mac has no PluginDatabase, nor does Chromium
   1360     if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType))
   1361         return WebCore::ObjectContentNetscapePlugin;
   1362 #endif
   1363 
   1364     if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
   1365         return WebCore::ObjectContentFrame;
   1366 
   1367     return WebCore::ObjectContentNone;
   1368 }
   1369 
   1370 static HTMLPlugInElement* toPlugInElement(Node* node)
   1371 {
   1372     if (!node)
   1373         return 0;
   1374 
   1375 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
   1376     ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag)
   1377         || node->hasTagName(videoTag) || node->hasTagName(audioTag)
   1378         || node->hasTagName(appletTag));
   1379 #else
   1380     ASSERT(node->hasTagName(objectTag) || node->hasTagName(embedTag)
   1381         || node->hasTagName(appletTag));
   1382 #endif
   1383 
   1384     return static_cast<HTMLPlugInElement*>(node);
   1385 }
   1386 
   1387 bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType,
   1388     const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
   1389 {
   1390     RefPtr<Widget> widget;
   1391 
   1392     if (renderer && !useFallback) {
   1393         HTMLPlugInElement* element = toPlugInElement(renderer->node());
   1394 
   1395         if (!SecurityOrigin::canLoad(url, String(), frame()->document())) {
   1396             FrameLoader::reportLocalLoadFailed(m_frame, url.string());
   1397             return false;
   1398         }
   1399 
   1400         checkIfRunInsecureContent(m_frame->document()->securityOrigin(), url);
   1401 
   1402         widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()),
   1403                                         element, url, paramNames, paramValues, mimeType,
   1404                                         m_frame->document()->isPluginDocument() && !m_containsPlugIns);
   1405         if (widget) {
   1406             renderer->setWidget(widget);
   1407             m_containsPlugIns = true;
   1408         }
   1409     }
   1410 
   1411     return widget != 0;
   1412 }
   1413 
   1414 String FrameLoader::outgoingReferrer() const
   1415 {
   1416     return m_outgoingReferrer;
   1417 }
   1418 
   1419 String FrameLoader::outgoingOrigin() const
   1420 {
   1421     return m_frame->document()->securityOrigin()->toString();
   1422 }
   1423 
   1424 bool FrameLoader::isMixedContent(SecurityOrigin* context, const KURL& url)
   1425 {
   1426     if (context->protocol() != "https")
   1427         return false;  // We only care about HTTPS security origins.
   1428 
   1429     if (!url.isValid() || url.protocolIs("https") || url.protocolIs("about") || url.protocolIs("data"))
   1430         return false;  // Loading these protocols is secure.
   1431 
   1432     return true;
   1433 }
   1434 
   1435 void FrameLoader::checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL& url)
   1436 {
   1437     if (!isMixedContent(context, url))
   1438         return;
   1439 
   1440     String message = String::format("The page at %s displayed insecure content from %s.\n",
   1441         m_URL.string().utf8().data(), url.string().utf8().data());
   1442     m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String());
   1443 
   1444     m_client->didDisplayInsecureContent();
   1445 }
   1446 
   1447 void FrameLoader::checkIfRunInsecureContent(SecurityOrigin* context, const KURL& url)
   1448 {
   1449     if (!isMixedContent(context, url))
   1450         return;
   1451 
   1452     String message = String::format("The page at %s ran insecure content from %s.\n",
   1453         m_URL.string().utf8().data(), url.string().utf8().data());
   1454     m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String());
   1455 
   1456     m_client->didRunInsecureContent(context);
   1457 }
   1458 
   1459 Frame* FrameLoader::opener()
   1460 {
   1461     return m_opener;
   1462 }
   1463 
   1464 void FrameLoader::setOpener(Frame* opener)
   1465 {
   1466     if (m_opener)
   1467         m_opener->loader()->m_openedFrames.remove(m_frame);
   1468     if (opener)
   1469         opener->loader()->m_openedFrames.add(m_frame);
   1470     m_opener = opener;
   1471 
   1472     if (m_frame->document()) {
   1473         m_frame->document()->initSecurityContext();
   1474         m_frame->domWindow()->setSecurityOrigin(m_frame->document()->securityOrigin());
   1475     }
   1476 }
   1477 
   1478 void FrameLoader::handleFallbackContent()
   1479 {
   1480     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
   1481     if (!owner || !owner->hasTagName(objectTag))
   1482         return;
   1483     static_cast<HTMLObjectElement*>(owner)->renderFallbackContent();
   1484 }
   1485 
   1486 void FrameLoader::provisionalLoadStarted()
   1487 {
   1488 #ifdef ANDROID_INSTRUMENT
   1489     if (!m_frame->tree()->parent())
   1490         android::TimeCounter::reset();
   1491 #endif
   1492     m_firstLayoutDone = false;
   1493     m_frame->redirectScheduler()->cancel(true);
   1494     m_client->provisionalLoadStarted();
   1495 }
   1496 
   1497 bool FrameLoader::isProcessingUserGesture()
   1498 {
   1499     Frame* frame = m_frame->tree()->top();
   1500     if (!frame->script()->canExecuteScripts())
   1501         return true; // If JavaScript is disabled, a user gesture must have initiated the navigation.
   1502     return frame->script()->processingUserGesture(mainThreadNormalWorld()); // FIXME: Use pageIsProcessingUserGesture.
   1503 }
   1504 
   1505 void FrameLoader::resetMultipleFormSubmissionProtection()
   1506 {
   1507     m_submittedFormURL = KURL();
   1508 }
   1509 
   1510 void FrameLoader::setEncoding(const String& name, bool userChosen)
   1511 {
   1512     if (!m_workingURL.isEmpty())
   1513         receivedFirstData();
   1514     m_encoding = name;
   1515     m_encodingWasChosenByUser = userChosen;
   1516 }
   1517 
   1518 void FrameLoader::addData(const char* bytes, int length)
   1519 {
   1520     ASSERT(m_workingURL.isEmpty());
   1521     ASSERT(m_frame->document());
   1522     ASSERT(m_frame->document()->parsing());
   1523     write(bytes, length);
   1524 }
   1525 
   1526 #if ENABLE(WML)
   1527 static inline bool frameContainsWMLContent(Frame* frame)
   1528 {
   1529     Document* document = frame ? frame->document() : 0;
   1530     if (!document)
   1531         return false;
   1532 
   1533     return document->containsWMLContent() || document->isWMLDocument();
   1534 }
   1535 #endif
   1536 
   1537 bool FrameLoader::canCachePageContainingThisFrame()
   1538 {
   1539     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
   1540         if (!child->loader()->canCachePageContainingThisFrame())
   1541             return false;
   1542     }
   1543 
   1544     return m_documentLoader
   1545         && m_documentLoader->mainDocumentError().isNull()
   1546         // FIXME: If we ever change this so that frames with plug-ins will be cached,
   1547         // we need to make sure that we don't cache frames that have outstanding NPObjects
   1548         // (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
   1549         // they would need to be destroyed and then recreated, and there is no way that we can recreate
   1550         // the right NPObjects. See <rdar://problem/5197041> for more information.
   1551         && !m_containsPlugIns
   1552         && !m_URL.protocolIs("https")
   1553         && (!m_frame->domWindow() || !m_frame->domWindow()->hasEventListeners(eventNames().unloadEvent))
   1554 #if ENABLE(DATABASE)
   1555         && !m_frame->document()->hasOpenDatabases()
   1556 #endif
   1557 #if ENABLE(SHARED_WORKERS)
   1558         && !SharedWorkerRepository::hasSharedWorkers(m_frame->document())
   1559 #endif
   1560         && !m_frame->document()->usingGeolocation()
   1561         && history()->currentItem()
   1562         && !m_quickRedirectComing
   1563         && !m_documentLoader->isLoadingInAPISense()
   1564         && !m_documentLoader->isStopping()
   1565         && m_frame->document()->canSuspendActiveDOMObjects()
   1566 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   1567         // FIXME: We should investigating caching frames that have an associated
   1568         // application cache. <rdar://problem/5917899> tracks that work.
   1569         && m_documentLoader->applicationCacheHost()->canCacheInPageCache()
   1570 #endif
   1571 #if ENABLE(WML)
   1572         && !frameContainsWMLContent(m_frame)
   1573 #endif
   1574         && m_client->canCachePage()
   1575         ;
   1576 }
   1577 
   1578 bool FrameLoader::canCachePage()
   1579 {
   1580 #ifndef NDEBUG
   1581     logCanCachePageDecision();
   1582 #endif
   1583 
   1584     // Cache the page, if possible.
   1585     // Don't write to the cache if in the middle of a redirect, since we will want to
   1586     // store the final page we end up on.
   1587     // No point writing to the cache on a reload or loadSame, since we will just write
   1588     // over it again when we leave that page.
   1589     // FIXME: <rdar://problem/4886592> - We should work out the complexities of caching pages with frames as they
   1590     // are the most interesting pages on the web, and often those that would benefit the most from caching!
   1591     FrameLoadType loadType = this->loadType();
   1592 
   1593     return !m_frame->tree()->parent()
   1594         && canCachePageContainingThisFrame()
   1595         && m_frame->page()
   1596         && m_frame->page()->backForwardList()->enabled()
   1597         && m_frame->page()->backForwardList()->capacity() > 0
   1598         && m_frame->page()->settings()->usesPageCache()
   1599         && loadType != FrameLoadTypeReload
   1600         && loadType != FrameLoadTypeReloadFromOrigin
   1601         && loadType != FrameLoadTypeSame
   1602         ;
   1603 }
   1604 
   1605 #ifndef NDEBUG
   1606 static String& pageCacheLogPrefix(int indentLevel)
   1607 {
   1608     static int previousIndent = -1;
   1609     DEFINE_STATIC_LOCAL(String, prefix, ());
   1610 
   1611     if (indentLevel != previousIndent) {
   1612         previousIndent = indentLevel;
   1613         prefix.truncate(0);
   1614         for (int i = 0; i < previousIndent; ++i)
   1615             prefix += "    ";
   1616     }
   1617 
   1618     return prefix;
   1619 }
   1620 
   1621 static void pageCacheLog(const String& prefix, const String& message)
   1622 {
   1623     LOG(PageCache, "%s%s", prefix.utf8().data(), message.utf8().data());
   1624 }
   1625 
   1626 #define PCLOG(...) pageCacheLog(pageCacheLogPrefix(indentLevel), String::format(__VA_ARGS__))
   1627 
   1628 void FrameLoader::logCanCachePageDecision()
   1629 {
   1630     // Only bother logging for main frames that have actually loaded and have content.
   1631     if (m_creatingInitialEmptyDocument)
   1632         return;
   1633     KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
   1634     if (currentURL.isEmpty())
   1635         return;
   1636 
   1637     int indentLevel = 0;
   1638     PCLOG("--------\n Determining if page can be cached:");
   1639 
   1640     bool cannotCache = !logCanCacheFrameDecision(1);
   1641 
   1642     FrameLoadType loadType = this->loadType();
   1643     do {
   1644         if (m_frame->tree()->parent())
   1645             { PCLOG("   -Frame has a parent frame"); cannotCache = true; }
   1646         if (!m_frame->page()) {
   1647             PCLOG("   -There is no Page object");
   1648             cannotCache = true;
   1649             break;
   1650         }
   1651         if (!m_frame->page()->backForwardList()->enabled())
   1652             { PCLOG("   -The back/forward list is disabled"); cannotCache = true; }
   1653         if (!(m_frame->page()->backForwardList()->capacity() > 0))
   1654             { PCLOG("   -The back/forward list has a 0 capacity"); cannotCache = true; }
   1655         if (!m_frame->page()->settings()->usesPageCache())
   1656             { PCLOG("   -Page settings says b/f cache disabled"); cannotCache = true; }
   1657         if (loadType == FrameLoadTypeReload)
   1658             { PCLOG("   -Load type is: Reload"); cannotCache = true; }
   1659         if (loadType == FrameLoadTypeReloadFromOrigin)
   1660             { PCLOG("   -Load type is: Reload from origin"); cannotCache = true; }
   1661         if (loadType == FrameLoadTypeSame)
   1662             { PCLOG("   -Load type is: Same"); cannotCache = true; }
   1663     } while (false);
   1664 
   1665     PCLOG(cannotCache ? " Page CANNOT be cached\n--------" : " Page CAN be cached\n--------");
   1666 }
   1667 
   1668 bool FrameLoader::logCanCacheFrameDecision(int indentLevel)
   1669 {
   1670     // Only bother logging for frames that have actually loaded and have content.
   1671     if (m_creatingInitialEmptyDocument)
   1672         return false;
   1673     KURL currentURL = m_documentLoader ? m_documentLoader->url() : KURL();
   1674     if (currentURL.isEmpty())
   1675         return false;
   1676 
   1677     PCLOG("+---");
   1678     KURL newURL = m_provisionalDocumentLoader ? m_provisionalDocumentLoader->url() : KURL();
   1679     if (!newURL.isEmpty())
   1680         PCLOG(" Determining if frame can be cached navigating from (%s) to (%s):", currentURL.string().utf8().data(), newURL.string().utf8().data());
   1681     else
   1682         PCLOG(" Determining if subframe with URL (%s) can be cached:", currentURL.string().utf8().data());
   1683 
   1684     bool cannotCache = false;
   1685 
   1686     do {
   1687         if (!m_documentLoader) {
   1688             PCLOG("   -There is no DocumentLoader object");
   1689             cannotCache = true;
   1690             break;
   1691         }
   1692         if (!m_documentLoader->mainDocumentError().isNull())
   1693             { PCLOG("   -Main document has an error"); cannotCache = true; }
   1694         if (m_containsPlugIns)
   1695             { PCLOG("   -Frame contains plugins"); cannotCache = true; }
   1696         if (m_URL.protocolIs("https"))
   1697             { PCLOG("   -Frame is HTTPS"); cannotCache = true; }
   1698         if (m_frame->domWindow() && m_frame->domWindow()->hasEventListeners(eventNames().unloadEvent))
   1699             { PCLOG("   -Frame has an unload event listener"); cannotCache = true; }
   1700 #if ENABLE(DATABASE)
   1701         if (m_frame->document()->hasOpenDatabases())
   1702             { PCLOG("   -Frame has open database handles"); cannotCache = true; }
   1703 #endif
   1704 #if ENABLE(SHARED_WORKERS)
   1705         if (SharedWorkerRepository::hasSharedWorkers(m_frame->document()))
   1706             { PCLOG("   -Frame has associated SharedWorkers"); cannotCache = true; }
   1707 #endif
   1708         if (m_frame->document()->usingGeolocation())
   1709             { PCLOG("   -Frame uses Geolocation"); cannotCache = true; }
   1710         if (!history()->currentItem())
   1711             { PCLOG("   -No current history item"); cannotCache = true; }
   1712         if (m_quickRedirectComing)
   1713             { PCLOG("   -Quick redirect is coming"); cannotCache = true; }
   1714         if (m_documentLoader->isLoadingInAPISense())
   1715             { PCLOG("   -DocumentLoader is still loading in API sense"); cannotCache = true; }
   1716         if (m_documentLoader->isStopping())
   1717             { PCLOG("   -DocumentLoader is in the middle of stopping"); cannotCache = true; }
   1718         if (!m_frame->document()->canSuspendActiveDOMObjects())
   1719             { PCLOG("   -The document cannot suspect its active DOM Objects"); cannotCache = true; }
   1720 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   1721         if (!m_documentLoader->applicationCacheHost()->canCacheInPageCache())
   1722             { PCLOG("   -The DocumentLoader uses an application cache"); cannotCache = true; }
   1723 #endif
   1724         if (!m_client->canCachePage())
   1725             { PCLOG("   -The client says this frame cannot be cached"); cannotCache = true; }
   1726     } while (false);
   1727 
   1728     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   1729         if (!child->loader()->logCanCacheFrameDecision(indentLevel + 1))
   1730             cannotCache = true;
   1731 
   1732     PCLOG(cannotCache ? " Frame CANNOT be cached" : " Frame CAN be cached");
   1733     PCLOG("+---");
   1734 
   1735     return !cannotCache;
   1736 }
   1737 #endif
   1738 
   1739 void FrameLoader::updateFirstPartyForCookies()
   1740 {
   1741     if (m_frame->tree()->parent())
   1742         setFirstPartyForCookies(m_frame->tree()->parent()->document()->firstPartyForCookies());
   1743     else
   1744         setFirstPartyForCookies(m_URL);
   1745 }
   1746 
   1747 void FrameLoader::setFirstPartyForCookies(const KURL& url)
   1748 {
   1749     m_frame->document()->setFirstPartyForCookies(url);
   1750     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   1751         child->loader()->setFirstPartyForCookies(url);
   1752 }
   1753 
   1754 // This does the same kind of work that didOpenURL does, except it relies on the fact
   1755 // that a higher level already checked that the URLs match and the scrolling is the right thing to do.
   1756 void FrameLoader::loadInSameDocument(const KURL& url, SerializedScriptValue* stateObject, bool isNewNavigation)
   1757 {
   1758     // If we have a state object, we cannot also be a new navigation.
   1759     ASSERT(!stateObject || (stateObject && !isNewNavigation));
   1760 
   1761     // Update the data source's request with the new URL to fake the URL change
   1762     m_frame->document()->setURL(url);
   1763     documentLoader()->replaceRequestURLForSameDocumentNavigation(url);
   1764     if (isNewNavigation && !shouldTreatURLAsSameAsCurrent(url) && !stateObject) {
   1765         // NB: must happen after replaceRequestURLForSameDocumentNavigation(), since we add
   1766         // based on the current request. Must also happen before we openURL and displace the
   1767         // scroll position, since adding the BF item will save away scroll state.
   1768 
   1769         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
   1770         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
   1771         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
   1772         // though its load is not yet done.  I think this all works out OK, for one because
   1773         // we have already saved away the scroll and doc state for the long slow load,
   1774         // but it's not an obvious case.
   1775 
   1776         history()->updateBackForwardListForFragmentScroll();
   1777     }
   1778 
   1779     bool hashChange = equalIgnoringFragmentIdentifier(url, m_URL) && url.fragmentIdentifier() != m_URL.fragmentIdentifier();
   1780     m_URL = url;
   1781     history()->updateForSameDocumentNavigation();
   1782 
   1783     // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor
   1784     if (hashChange)
   1785         m_frame->eventHandler()->stopAutoscrollTimer();
   1786 
   1787     // It's important to model this as a load that starts and immediately finishes.
   1788     // Otherwise, the parent frame may think we never finished loading.
   1789     started();
   1790 
   1791     if (hashChange) {
   1792         if (FrameView* view = m_frame->view())
   1793             view->scrollToFragment(m_URL);
   1794     }
   1795 
   1796     m_isComplete = false;
   1797     checkCompleted();
   1798 
   1799     if (isNewNavigation) {
   1800         // This will clear previousItem from the rest of the frame tree that didn't
   1801         // doing any loading. We need to make a pass on this now, since for anchor nav
   1802         // we'll not go through a real load and reach Completed state.
   1803         checkLoadComplete();
   1804     }
   1805 
   1806     if (stateObject) {
   1807         m_frame->document()->statePopped(stateObject);
   1808         m_client->dispatchDidPopStateWithinPage();
   1809     }
   1810 
   1811     if (hashChange) {
   1812         m_frame->document()->dispatchWindowEvent(Event::create(eventNames().hashchangeEvent, false, false));
   1813         m_client->dispatchDidChangeLocationWithinPage();
   1814     }
   1815 
   1816     // FrameLoaderClient::didFinishLoad() tells the internal load delegate the load finished with no error
   1817     m_client->didFinishLoad();
   1818 }
   1819 
   1820 bool FrameLoader::isComplete() const
   1821 {
   1822     return m_isComplete;
   1823 }
   1824 
   1825 void FrameLoader::completed()
   1826 {
   1827     RefPtr<Frame> protect(m_frame);
   1828 
   1829     for (Frame* descendant = m_frame->tree()->traverseNext(m_frame); descendant; descendant = descendant->tree()->traverseNext(m_frame))
   1830         descendant->redirectScheduler()->startTimer();
   1831 
   1832     if (Frame* parent = m_frame->tree()->parent())
   1833         parent->loader()->checkCompleted();
   1834 
   1835     if (m_frame->view())
   1836         m_frame->view()->maintainScrollPositionAtAnchor(0);
   1837 }
   1838 
   1839 void FrameLoader::started()
   1840 {
   1841     for (Frame* frame = m_frame; frame; frame = frame->tree()->parent())
   1842         frame->loader()->m_isComplete = false;
   1843 }
   1844 
   1845 bool FrameLoader::containsPlugins() const
   1846 {
   1847     return m_containsPlugIns;
   1848 }
   1849 
   1850 void FrameLoader::prepareForLoadStart()
   1851 {
   1852     if (Page* page = m_frame->page())
   1853         page->progress()->progressStarted(m_frame);
   1854     m_client->dispatchDidStartProvisionalLoad();
   1855 }
   1856 
   1857 void FrameLoader::setupForReplace()
   1858 {
   1859     setState(FrameStateProvisional);
   1860     m_provisionalDocumentLoader = m_documentLoader;
   1861     m_documentLoader = 0;
   1862     detachChildren();
   1863 }
   1864 
   1865 void FrameLoader::setupForReplaceByMIMEType(const String& newMIMEType)
   1866 {
   1867     activeDocumentLoader()->setupForReplaceByMIMEType(newMIMEType);
   1868 }
   1869 
   1870 // This is a hack to allow keep navigation to http/https feeds working. To remove this
   1871 // we need to introduce new API akin to registerURLSchemeAsLocal, that registers a
   1872 // protocols navigation policy.
   1873 static bool isFeedWithNestedProtocolInHTTPFamily(const KURL& url)
   1874 {
   1875     const String& urlString = url.string();
   1876     if (!urlString.startsWith("feed", false))
   1877         return false;
   1878 
   1879     return urlString.startsWith("feed://", false)
   1880         || urlString.startsWith("feed:http:", false) || urlString.startsWith("feed:https:", false)
   1881         || urlString.startsWith("feeds:http:", false) || urlString.startsWith("feeds:https:", false)
   1882         || urlString.startsWith("feedsearch:http:", false) || urlString.startsWith("feedsearch:https:", false);
   1883 }
   1884 
   1885 void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList,
   1886     PassRefPtr<Event> event, PassRefPtr<FormState> formState, ReferrerPolicy referrerPolicy)
   1887 {
   1888     KURL url = request.resourceRequest().url();
   1889 
   1890     String referrer;
   1891     String argsReferrer = request.resourceRequest().httpReferrer();
   1892     if (!argsReferrer.isEmpty())
   1893         referrer = argsReferrer;
   1894     else
   1895         referrer = m_outgoingReferrer;
   1896 
   1897     ASSERT(frame()->document());
   1898     if (SecurityOrigin::shouldTreatURLAsLocal(url.string()) && !isFeedWithNestedProtocolInHTTPFamily(url)) {
   1899         if (!SecurityOrigin::canLoad(url, String(), frame()->document()) && !SecurityOrigin::canLoad(url, referrer, 0)) {
   1900             FrameLoader::reportLocalLoadFailed(m_frame, url.string());
   1901             return;
   1902         }
   1903     }
   1904 
   1905     if (SecurityOrigin::shouldHideReferrer(url, referrer) || referrerPolicy == NoReferrer)
   1906         referrer = String();
   1907 
   1908     FrameLoadType loadType;
   1909     if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
   1910         loadType = FrameLoadTypeReload;
   1911     else if (lockBackForwardList)
   1912         loadType = FrameLoadTypeRedirectWithLockedBackForwardList;
   1913     else
   1914         loadType = FrameLoadTypeStandard;
   1915 
   1916 #ifdef ANDROID_USER_GESTURE
   1917     if (request.resourceRequest().httpMethod() == "POST")
   1918         loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.get(), request.resourceRequest().getUserGesture());
   1919     else
   1920         loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.get(), request.resourceRequest().getUserGesture());
   1921 #else
   1922     if (request.resourceRequest().httpMethod() == "POST")
   1923         loadPostRequest(request.resourceRequest(), referrer, request.frameName(), lockHistory, loadType, event, formState.get());
   1924     else
   1925         loadURL(request.resourceRequest().url(), referrer, request.frameName(), lockHistory, loadType, event, formState.get());
   1926 #endif
   1927 
   1928     // FIXME: It's possible this targetFrame will not be the same frame that was targeted by the actual
   1929     // load if frame names have changed.
   1930     Frame* sourceFrame = formState ? formState->sourceFrame() : m_frame;
   1931     Frame* targetFrame = sourceFrame->loader()->findFrameForNavigation(request.frameName());
   1932     if (targetFrame && targetFrame != sourceFrame) {
   1933         if (Page* page = targetFrame->page())
   1934 #ifdef ANDROID_USER_GESTURE
   1935             page->chrome()->focus(request.resourceRequest().getUserGesture());
   1936 #else
   1937             page->chrome()->focus();
   1938 #endif
   1939     }
   1940 }
   1941 
   1942 #ifdef ANDROID_USER_GESTURE
   1943 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
   1944     PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState, bool userGesture)
   1945 #else
   1946 void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType newLoadType,
   1947     PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState)
   1948 #endif
   1949 {
   1950     RefPtr<FormState> formState = prpFormState;
   1951     bool isFormSubmission = formState;
   1952 
   1953     ResourceRequest request(newURL);
   1954 #ifdef ANDROID_USER_GESTURE
   1955     request.setUserGesture(userGesture);
   1956 #endif
   1957     if (!referrer.isEmpty()) {
   1958         request.setHTTPReferrer(referrer);
   1959         RefPtr<SecurityOrigin> referrerOrigin = SecurityOrigin::createFromString(referrer);
   1960         addHTTPOriginIfNeeded(request, referrerOrigin->toString());
   1961     }
   1962     addExtraFieldsToRequest(request, newLoadType, true, event || isFormSubmission);
   1963     if (newLoadType == FrameLoadTypeReload || newLoadType == FrameLoadTypeReloadFromOrigin)
   1964         request.setCachePolicy(ReloadIgnoringCacheData);
   1965 
   1966     ASSERT(newLoadType != FrameLoadTypeSame);
   1967 
   1968     // The search for a target frame is done earlier in the case of form submission.
   1969     Frame* targetFrame = isFormSubmission ? 0 : findFrameForNavigation(frameName);
   1970     if (targetFrame && targetFrame != m_frame) {
   1971 #ifdef ANDROID_USER_GESTURE
   1972         targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState.release(), userGesture);
   1973 #else
   1974         targetFrame->loader()->loadURL(newURL, referrer, String(), lockHistory, newLoadType, event, formState.release());
   1975 #endif
   1976         return;
   1977     }
   1978 
   1979     if (m_unloadEventBeingDispatched)
   1980         return;
   1981 
   1982     NavigationAction action(newURL, newLoadType, isFormSubmission, event);
   1983 
   1984     if (!targetFrame && !frameName.isEmpty()) {
   1985         policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy,
   1986             request, formState.release(), frameName, this);
   1987         return;
   1988     }
   1989 
   1990     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
   1991 
   1992     bool sameURL = shouldTreatURLAsSameAsCurrent(newURL);
   1993 
   1994     // Make sure to do scroll to anchor processing even if the URL is
   1995     // exactly the same so pages with '#' links and DHTML side effects
   1996     // work properly.
   1997     if (shouldScrollToAnchor(isFormSubmission, newLoadType, newURL)) {
   1998         oldDocumentLoader->setTriggeringAction(action);
   1999         policyChecker()->stopCheck();
   2000         policyChecker()->setLoadType(newLoadType);
   2001         policyChecker()->checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
   2002             callContinueFragmentScrollAfterNavigationPolicy, this);
   2003     } else {
   2004         // must grab this now, since this load may stop the previous load and clear this flag
   2005         bool isRedirect = m_quickRedirectComing;
   2006         loadWithNavigationAction(request, action, lockHistory, newLoadType, formState.release());
   2007         if (isRedirect) {
   2008             m_quickRedirectComing = false;
   2009             if (m_provisionalDocumentLoader)
   2010                 m_provisionalDocumentLoader->setIsClientRedirect(true);
   2011         } else if (sameURL)
   2012             // Example of this case are sites that reload the same URL with a different cookie
   2013             // driving the generated content, or a master frame with links that drive a target
   2014             // frame, where the user has clicked on the same link repeatedly.
   2015             m_loadType = FrameLoadTypeSame;
   2016     }
   2017 }
   2018 
   2019 void FrameLoader::load(const ResourceRequest& request, bool lockHistory)
   2020 {
   2021     load(request, SubstituteData(), lockHistory);
   2022 }
   2023 
   2024 void FrameLoader::load(const ResourceRequest& request, const SubstituteData& substituteData, bool lockHistory)
   2025 {
   2026     if (m_inStopAllLoaders)
   2027         return;
   2028 
   2029     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
   2030     m_loadType = FrameLoadTypeStandard;
   2031     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, substituteData);
   2032     if (lockHistory && m_documentLoader)
   2033         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory());
   2034     load(loader.get());
   2035 }
   2036 
   2037 void FrameLoader::load(const ResourceRequest& request, const String& frameName, bool lockHistory)
   2038 {
   2039     if (frameName.isEmpty()) {
   2040         load(request, lockHistory);
   2041         return;
   2042     }
   2043 
   2044     Frame* frame = findFrameForNavigation(frameName);
   2045     if (frame) {
   2046         frame->loader()->load(request, lockHistory);
   2047         return;
   2048     }
   2049 
   2050     policyChecker()->checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), FrameLoader::callContinueLoadAfterNewWindowPolicy, request, 0, frameName, this);
   2051 }
   2052 
   2053 void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState)
   2054 {
   2055     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
   2056     if (lockHistory && m_documentLoader)
   2057         loader->setClientRedirectSourceForHistory(m_documentLoader->didCreateGlobalHistoryEntry() ? m_documentLoader->urlForHistory() : m_documentLoader->clientRedirectSourceForHistory());
   2058 
   2059     loader->setTriggeringAction(action);
   2060     if (m_documentLoader)
   2061         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   2062 
   2063     loadWithDocumentLoader(loader.get(), type, formState);
   2064 }
   2065 
   2066 void FrameLoader::load(DocumentLoader* newDocumentLoader)
   2067 {
   2068     ResourceRequest& r = newDocumentLoader->request();
   2069     addExtraFieldsToMainResourceRequest(r);
   2070     FrameLoadType type;
   2071 
   2072     if (shouldTreatURLAsSameAsCurrent(newDocumentLoader->originalRequest().url())) {
   2073         r.setCachePolicy(ReloadIgnoringCacheData);
   2074         type = FrameLoadTypeSame;
   2075     } else
   2076         type = FrameLoadTypeStandard;
   2077 
   2078     if (m_documentLoader)
   2079         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   2080 
   2081     // When we loading alternate content for an unreachable URL that we're
   2082     // visiting in the history list, we treat it as a reload so the history list
   2083     // is appropriately maintained.
   2084     //
   2085     // FIXME: This seems like a dangerous overloading of the meaning of "FrameLoadTypeReload" ...
   2086     // shouldn't a more explicit type of reload be defined, that means roughly
   2087     // "load without affecting history" ?
   2088     if (shouldReloadToHandleUnreachableURL(newDocumentLoader)) {
   2089         ASSERT(type == FrameLoadTypeStandard);
   2090         type = FrameLoadTypeReload;
   2091     }
   2092 
   2093     loadWithDocumentLoader(newDocumentLoader, type, 0);
   2094 }
   2095 
   2096 void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> prpFormState)
   2097 {
   2098     ASSERT(m_client->hasWebView());
   2099 
   2100     // Unfortunately the view must be non-nil, this is ultimately due
   2101     // to parser requiring a FrameView.  We should fix this dependency.
   2102 
   2103     ASSERT(m_frame->view());
   2104 
   2105     if (m_unloadEventBeingDispatched)
   2106         return;
   2107 
   2108     policyChecker()->setLoadType(type);
   2109     RefPtr<FormState> formState = prpFormState;
   2110     bool isFormSubmission = formState;
   2111 
   2112     const KURL& newURL = loader->request().url();
   2113 
   2114     if (shouldScrollToAnchor(isFormSubmission, policyChecker()->loadType(), newURL)) {
   2115         RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
   2116         NavigationAction action(newURL, policyChecker()->loadType(), isFormSubmission);
   2117 
   2118         oldDocumentLoader->setTriggeringAction(action);
   2119         policyChecker()->stopCheck();
   2120         policyChecker()->checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
   2121             callContinueFragmentScrollAfterNavigationPolicy, this);
   2122     } else {
   2123         if (Frame* parent = m_frame->tree()->parent())
   2124             loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
   2125 
   2126         policyChecker()->stopCheck();
   2127         setPolicyDocumentLoader(loader);
   2128         if (loader->triggeringAction().isEmpty())
   2129             loader->setTriggeringAction(NavigationAction(newURL, policyChecker()->loadType(), isFormSubmission));
   2130 
   2131         if (Element* ownerElement = m_frame->document()->ownerElement()) {
   2132             if (!ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) {
   2133                 continueLoadAfterNavigationPolicy(loader->request(), formState, false);
   2134                 return;
   2135             }
   2136         }
   2137 
   2138         policyChecker()->checkNavigationPolicy(loader->request(), loader, formState,
   2139             callContinueLoadAfterNavigationPolicy, this);
   2140     }
   2141 }
   2142 
   2143 void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
   2144 {
   2145     ASSERT(!url.isEmpty());
   2146     if (!frame)
   2147         return;
   2148 
   2149     frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
   2150 }
   2151 
   2152 const ResourceRequest& FrameLoader::initialRequest() const
   2153 {
   2154     return activeDocumentLoader()->originalRequest();
   2155 }
   2156 
   2157 void FrameLoader::receivedData(const char* data, int length)
   2158 {
   2159     activeDocumentLoader()->receivedData(data, length);
   2160 }
   2161 
   2162 bool FrameLoader::willLoadMediaElementURL(KURL& url)
   2163 {
   2164     ResourceRequest request(url);
   2165 
   2166     unsigned long identifier;
   2167     ResourceError error;
   2168     requestFromDelegate(request, identifier, error);
   2169     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), -1, error);
   2170 
   2171     url = request.url();
   2172 
   2173     return error.isNull();
   2174 }
   2175 
   2176 ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
   2177 {
   2178     return m_client->interruptForPolicyChangeError(request);
   2179 }
   2180 
   2181 bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
   2182 {
   2183     KURL unreachableURL = docLoader->unreachableURL();
   2184 
   2185     if (unreachableURL.isEmpty())
   2186         return false;
   2187 
   2188     if (!isBackForwardLoadType(policyChecker()->loadType()))
   2189         return false;
   2190 
   2191     // We only treat unreachableURLs specially during the delegate callbacks
   2192     // for provisional load errors and navigation policy decisions. The former
   2193     // case handles well-formed URLs that can't be loaded, and the latter
   2194     // case handles malformed URLs and unknown schemes. Loading alternate content
   2195     // at other times behaves like a standard load.
   2196     DocumentLoader* compareDocumentLoader = 0;
   2197     if (policyChecker()->delegateIsDecidingNavigationPolicy() || policyChecker()->delegateIsHandlingUnimplementablePolicy())
   2198         compareDocumentLoader = m_policyDocumentLoader.get();
   2199     else if (m_delegateIsHandlingProvisionalLoadError)
   2200         compareDocumentLoader = m_provisionalDocumentLoader.get();
   2201 
   2202     return compareDocumentLoader && unreachableURL == compareDocumentLoader->request().url();
   2203 }
   2204 
   2205 void FrameLoader::reloadWithOverrideEncoding(const String& encoding)
   2206 {
   2207     if (!m_documentLoader)
   2208         return;
   2209 
   2210     ResourceRequest request = m_documentLoader->request();
   2211     KURL unreachableURL = m_documentLoader->unreachableURL();
   2212     if (!unreachableURL.isEmpty())
   2213         request.setURL(unreachableURL);
   2214 
   2215     request.setCachePolicy(ReturnCacheDataElseLoad);
   2216 
   2217     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request, SubstituteData());
   2218     setPolicyDocumentLoader(loader.get());
   2219 
   2220     loader->setOverrideEncoding(encoding);
   2221 
   2222     loadWithDocumentLoader(loader.get(), FrameLoadTypeReload, 0);
   2223 }
   2224 
   2225 void FrameLoader::reload(bool endToEndReload)
   2226 {
   2227     if (!m_documentLoader)
   2228         return;
   2229 
   2230     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
   2231     // Reloading in this case will lose the current contents (see 4151001).
   2232     if (m_documentLoader->request().url().isEmpty())
   2233         return;
   2234 
   2235     ResourceRequest initialRequest = m_documentLoader->request();
   2236 
   2237     // Replace error-page URL with the URL we were trying to reach.
   2238     KURL unreachableURL = m_documentLoader->unreachableURL();
   2239     if (!unreachableURL.isEmpty())
   2240         initialRequest.setURL(unreachableURL);
   2241 
   2242     // Create a new document loader for the reload, this will become m_documentLoader eventually,
   2243     // but first it has to be the "policy" document loader, and then the "provisional" document loader.
   2244     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest, SubstituteData());
   2245 
   2246     ResourceRequest& request = loader->request();
   2247 
   2248     // FIXME: We don't have a mechanism to revalidate the main resource without reloading at the moment.
   2249     request.setCachePolicy(ReloadIgnoringCacheData);
   2250 
   2251     // If we're about to re-post, set up action so the application can warn the user.
   2252     if (request.httpMethod() == "POST")
   2253         loader->setTriggeringAction(NavigationAction(request.url(), NavigationTypeFormResubmitted));
   2254 
   2255     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
   2256 
   2257     loadWithDocumentLoader(loader.get(), endToEndReload ? FrameLoadTypeReloadFromOrigin : FrameLoadTypeReload, 0);
   2258 }
   2259 
   2260 static bool canAccessAncestor(const SecurityOrigin* activeSecurityOrigin, Frame* targetFrame)
   2261 {
   2262     // targetFrame can be NULL when we're trying to navigate a top-level frame
   2263     // that has a NULL opener.
   2264     if (!targetFrame)
   2265         return false;
   2266 
   2267     for (Frame* ancestorFrame = targetFrame; ancestorFrame; ancestorFrame = ancestorFrame->tree()->parent()) {
   2268         Document* ancestorDocument = ancestorFrame->document();
   2269         if (!ancestorDocument)
   2270             return true;
   2271 
   2272         const SecurityOrigin* ancestorSecurityOrigin = ancestorDocument->securityOrigin();
   2273         if (activeSecurityOrigin->canAccess(ancestorSecurityOrigin))
   2274             return true;
   2275     }
   2276 
   2277     return false;
   2278 }
   2279 
   2280 bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
   2281 {
   2282     // The navigation change is safe if the active frame is:
   2283     //   - in the same security origin as the target or one of the target's
   2284     //     ancestors.
   2285     //
   2286     // Or the target frame is:
   2287     //   - a top-level frame in the frame hierarchy and the active frame can
   2288     //     navigate the target frame's opener per above or it is the opener of
   2289     //     the target frame.
   2290 
   2291     if (!targetFrame)
   2292         return true;
   2293 
   2294     // Performance optimization.
   2295     if (m_frame == targetFrame)
   2296         return true;
   2297 
   2298     // A sandboxed frame can only navigate itself and its descendants.
   2299     if (isDocumentSandboxed(SandboxNavigation) && !targetFrame->tree()->isDescendantOf(m_frame))
   2300         return false;
   2301 
   2302     // Let a frame navigate the top-level window that contains it.  This is
   2303     // important to allow because it lets a site "frame-bust" (escape from a
   2304     // frame created by another web site).
   2305     if (targetFrame == m_frame->tree()->top())
   2306         return true;
   2307 
   2308     // Let a frame navigate its opener if the opener is a top-level window.
   2309     if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetFrame)
   2310         return true;
   2311 
   2312     Document* activeDocument = m_frame->document();
   2313     ASSERT(activeDocument);
   2314     const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
   2315 
   2316     // For top-level windows, check the opener.
   2317     if (!targetFrame->tree()->parent() && canAccessAncestor(activeSecurityOrigin, targetFrame->loader()->opener()))
   2318         return true;
   2319 
   2320     // In general, check the frame's ancestors.
   2321     if (canAccessAncestor(activeSecurityOrigin, targetFrame))
   2322         return true;
   2323 
   2324     Settings* settings = targetFrame->settings();
   2325     if (settings && !settings->privateBrowsingEnabled()) {
   2326         Document* targetDocument = targetFrame->document();
   2327         // FIXME: this error message should contain more specifics of why the navigation change is not allowed.
   2328         String message = String::format("Unsafe JavaScript attempt to initiate a navigation change for frame with URL %s from frame with URL %s.\n",
   2329             targetDocument->url().string().utf8().data(), activeDocument->url().string().utf8().data());
   2330 
   2331         // FIXME: should we print to the console of the activeFrame as well?
   2332         targetFrame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
   2333     }
   2334 
   2335     return false;
   2336 }
   2337 
   2338 void FrameLoader::stopLoadingSubframes()
   2339 {
   2340     for (RefPtr<Frame> child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   2341         child->loader()->stopAllLoaders();
   2342 }
   2343 
   2344 void FrameLoader::stopAllLoaders(DatabasePolicy databasePolicy)
   2345 {
   2346     ASSERT(!m_frame->document() || !m_frame->document()->inPageCache());
   2347     if (m_unloadEventBeingDispatched)
   2348         return;
   2349 
   2350     // If this method is called from within this method, infinite recursion can occur (3442218). Avoid this.
   2351     if (m_inStopAllLoaders)
   2352         return;
   2353 
   2354     m_inStopAllLoaders = true;
   2355 
   2356     policyChecker()->stopCheck();
   2357 
   2358     stopLoadingSubframes();
   2359     if (m_provisionalDocumentLoader)
   2360         m_provisionalDocumentLoader->stopLoading(databasePolicy);
   2361     if (m_documentLoader)
   2362         m_documentLoader->stopLoading(databasePolicy);
   2363 
   2364     setProvisionalDocumentLoader(0);
   2365 
   2366 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
   2367     if (m_documentLoader)
   2368         m_documentLoader->clearArchiveResources();
   2369 #endif
   2370 
   2371     m_checkTimer.stop();
   2372 
   2373     m_inStopAllLoaders = false;
   2374 }
   2375 
   2376 void FrameLoader::stopForUserCancel(bool deferCheckLoadComplete)
   2377 {
   2378     stopAllLoaders();
   2379 
   2380     if (deferCheckLoadComplete)
   2381         scheduleCheckLoadComplete();
   2382     else if (m_frame->page())
   2383         checkLoadComplete();
   2384 }
   2385 
   2386 DocumentLoader* FrameLoader::activeDocumentLoader() const
   2387 {
   2388     if (m_state == FrameStateProvisional)
   2389         return m_provisionalDocumentLoader.get();
   2390     return m_documentLoader.get();
   2391 }
   2392 
   2393 bool FrameLoader::isLoading() const
   2394 {
   2395     DocumentLoader* docLoader = activeDocumentLoader();
   2396     if (!docLoader)
   2397         return false;
   2398     return docLoader->isLoadingMainResource() || docLoader->isLoadingSubresources() || docLoader->isLoadingPlugIns();
   2399 }
   2400 
   2401 bool FrameLoader::frameHasLoaded() const
   2402 {
   2403     return m_committedFirstRealDocumentLoad || (m_provisionalDocumentLoader && !m_creatingInitialEmptyDocument);
   2404 }
   2405 
   2406 void FrameLoader::setDocumentLoader(DocumentLoader* loader)
   2407 {
   2408     if (!loader && !m_documentLoader)
   2409         return;
   2410 
   2411     ASSERT(loader != m_documentLoader);
   2412     ASSERT(!loader || loader->frameLoader() == this);
   2413 
   2414     m_client->prepareForDataSourceReplacement();
   2415     detachChildren();
   2416     if (m_documentLoader)
   2417         m_documentLoader->detachFromFrame();
   2418 
   2419     m_documentLoader = loader;
   2420 }
   2421 
   2422 void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
   2423 {
   2424     if (m_policyDocumentLoader == loader)
   2425         return;
   2426 
   2427     ASSERT(m_frame);
   2428     if (loader)
   2429         loader->setFrame(m_frame);
   2430     if (m_policyDocumentLoader
   2431             && m_policyDocumentLoader != m_provisionalDocumentLoader
   2432             && m_policyDocumentLoader != m_documentLoader)
   2433         m_policyDocumentLoader->detachFromFrame();
   2434 
   2435     m_policyDocumentLoader = loader;
   2436 }
   2437 
   2438 void FrameLoader::setProvisionalDocumentLoader(DocumentLoader* loader)
   2439 {
   2440     ASSERT(!loader || !m_provisionalDocumentLoader);
   2441     ASSERT(!loader || loader->frameLoader() == this);
   2442 
   2443     if (m_provisionalDocumentLoader && m_provisionalDocumentLoader != m_documentLoader)
   2444         m_provisionalDocumentLoader->detachFromFrame();
   2445 
   2446     m_provisionalDocumentLoader = loader;
   2447 }
   2448 
   2449 double FrameLoader::timeOfLastCompletedLoad()
   2450 {
   2451     return storedTimeOfLastCompletedLoad;
   2452 }
   2453 
   2454 void FrameLoader::setState(FrameState newState)
   2455 {
   2456     m_state = newState;
   2457 
   2458     if (newState == FrameStateProvisional)
   2459         provisionalLoadStarted();
   2460     else if (newState == FrameStateComplete) {
   2461         frameLoadCompleted();
   2462         storedTimeOfLastCompletedLoad = currentTime();
   2463         if (m_documentLoader)
   2464             m_documentLoader->stopRecordingResponses();
   2465     }
   2466 }
   2467 
   2468 void FrameLoader::clearProvisionalLoad()
   2469 {
   2470     setProvisionalDocumentLoader(0);
   2471     if (Page* page = m_frame->page())
   2472         page->progress()->progressCompleted(m_frame);
   2473     setState(FrameStateComplete);
   2474 }
   2475 
   2476 void FrameLoader::markLoadComplete()
   2477 {
   2478     setState(FrameStateComplete);
   2479 }
   2480 
   2481 void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
   2482 {
   2483     RefPtr<CachedPage> cachedPage = prpCachedPage;
   2484     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
   2485 
   2486     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(),
   2487         pdl ? pdl->url().string().utf8().data() : "<no provisional DocumentLoader>");
   2488 
   2489     // Check to see if we need to cache the page we are navigating away from into the back/forward cache.
   2490     // We are doing this here because we know for sure that a new page is about to be loaded.
   2491     cachePageForHistoryItem(history()->currentItem());
   2492 
   2493     if (m_loadType != FrameLoadTypeReplace)
   2494         closeOldDataSources();
   2495 
   2496     if (!cachedPage && !m_creatingInitialEmptyDocument)
   2497         m_client->makeRepresentation(pdl.get());
   2498 
   2499     transitionToCommitted(cachedPage);
   2500 
   2501     // Call clientRedirectCancelledOrFinished() here so that the frame load delegate is notified that the redirect's
   2502     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
   2503     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
   2504     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
   2505     if (m_sentRedirectNotification)
   2506         clientRedirectCancelledOrFinished(false);
   2507 
   2508     if (cachedPage && cachedPage->document())
   2509         open(*cachedPage);
   2510     else {
   2511         KURL url = pdl->substituteData().responseURL();
   2512         if (url.isEmpty())
   2513             url = pdl->url();
   2514         if (url.isEmpty())
   2515             url = pdl->responseURL();
   2516         if (url.isEmpty())
   2517             url = blankURL();
   2518 
   2519         didOpenURL(url);
   2520     }
   2521 
   2522     LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data());
   2523 
   2524     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
   2525         history()->updateForClientRedirect();
   2526 
   2527     if (m_loadingFromCachedPage) {
   2528         m_frame->document()->documentDidBecomeActive();
   2529 
   2530         // Force a layout to update view size and thereby update scrollbars.
   2531         m_frame->view()->forceLayout();
   2532 
   2533         const ResponseVector& responses = m_documentLoader->responses();
   2534         size_t count = responses.size();
   2535         for (size_t i = 0; i < count; i++) {
   2536             const ResourceResponse& response = responses[i];
   2537             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
   2538             ResourceError error;
   2539             unsigned long identifier;
   2540             ResourceRequest request(response.url());
   2541             requestFromDelegate(request, identifier, error);
   2542             // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing.
   2543             // However, with today's computers and networking speeds, this won't happen in practice.
   2544             // Could be an issue with a giant local file.
   2545             notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, static_cast<int>(response.expectedContentLength()), error);
   2546         }
   2547 
   2548         pageCache()->remove(history()->currentItem());
   2549 
   2550         m_documentLoader->setPrimaryLoadComplete(true);
   2551 
   2552         // FIXME: Why only this frame and not parent frames?
   2553         checkLoadCompleteForThisFrame();
   2554     }
   2555 }
   2556 
   2557 void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
   2558 {
   2559     ASSERT(m_client->hasWebView());
   2560     ASSERT(m_state == FrameStateProvisional);
   2561 
   2562     if (m_state != FrameStateProvisional)
   2563         return;
   2564 
   2565     m_client->setCopiesOnScroll();
   2566     history()->updateForCommit();
   2567 
   2568     // The call to closeURL() invokes the unload event handler, which can execute arbitrary
   2569     // JavaScript. If the script initiates a new load, we need to abandon the current load,
   2570     // or the two will stomp each other.
   2571     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
   2572     if (m_documentLoader)
   2573         closeURL();
   2574     if (pdl != m_provisionalDocumentLoader)
   2575         return;
   2576 
   2577     // Nothing else can interupt this commit - set the Provisional->Committed transition in stone
   2578     if (m_documentLoader)
   2579         m_documentLoader->stopLoadingSubresources();
   2580     if (m_documentLoader)
   2581         m_documentLoader->stopLoadingPlugIns();
   2582 
   2583     setDocumentLoader(m_provisionalDocumentLoader.get());
   2584     setProvisionalDocumentLoader(0);
   2585     setState(FrameStateCommittedPage);
   2586 
   2587     // Handle adding the URL to the back/forward list.
   2588     DocumentLoader* dl = m_documentLoader.get();
   2589     String ptitle = dl->title();
   2590 
   2591     switch (m_loadType) {
   2592         case FrameLoadTypeForward:
   2593         case FrameLoadTypeBack:
   2594         case FrameLoadTypeBackWMLDeckNotAccessible:
   2595         case FrameLoadTypeIndexedBackForward:
   2596             if (Page* page = m_frame->page()) {
   2597                 if (page->backForwardList()) {
   2598                     history()->updateForBackForwardNavigation();
   2599 
   2600                     if (history()->currentItem())
   2601                         m_pendingStateObject = history()->currentItem()->stateObject();
   2602 
   2603                     // Create a document view for this document, or used the cached view.
   2604                     if (cachedPage) {
   2605                         DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
   2606                         ASSERT(cachedDocumentLoader);
   2607                         cachedDocumentLoader->setFrame(m_frame);
   2608                         m_client->transitionToCommittedFromCachedFrame(cachedPage->cachedMainFrame());
   2609 
   2610                     } else
   2611                         m_client->transitionToCommittedForNewPage();
   2612                 }
   2613             }
   2614             break;
   2615 
   2616         case FrameLoadTypeReload:
   2617         case FrameLoadTypeReloadFromOrigin:
   2618         case FrameLoadTypeSame:
   2619         case FrameLoadTypeReplace:
   2620             history()->updateForReload();
   2621             m_client->transitionToCommittedForNewPage();
   2622             break;
   2623 
   2624         case FrameLoadTypeStandard:
   2625             history()->updateForStandardLoad();
   2626 #ifndef BUILDING_ON_TIGER
   2627             // This code was originally added for a Leopard performance imporvement. We decided to
   2628             // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>.
   2629             if (m_frame->view())
   2630                 m_frame->view()->setScrollbarsSuppressed(true);
   2631 #endif
   2632             m_client->transitionToCommittedForNewPage();
   2633             break;
   2634 
   2635         case FrameLoadTypeRedirectWithLockedBackForwardList:
   2636             history()->updateForRedirectWithLockedBackForwardList();
   2637             m_client->transitionToCommittedForNewPage();
   2638             break;
   2639 
   2640         // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
   2641         // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
   2642         default:
   2643             ASSERT_NOT_REACHED();
   2644     }
   2645 
   2646     m_responseMIMEType = dl->responseMIMEType();
   2647 
   2648     // Tell the client we've committed this URL.
   2649     ASSERT(m_frame->view());
   2650 
   2651     if (m_creatingInitialEmptyDocument)
   2652         return;
   2653 
   2654     m_committedFirstRealDocumentLoad = true;
   2655 
   2656     if (!m_client->hasHTMLView())
   2657         receivedFirstData();
   2658     else if (cachedPage) {
   2659         // For non-cached HTML pages, these methods are called in receivedFirstData().
   2660         dispatchDidCommitLoad();
   2661 
   2662         // If we have a title let the WebView know about it.
   2663         if (!ptitle.isNull())
   2664             m_client->dispatchDidReceiveTitle(ptitle);
   2665     }
   2666 }
   2667 
   2668 void FrameLoader::clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress)
   2669 {
   2670     // Note that -webView:didCancelClientRedirectForFrame: is called on the frame load delegate even if
   2671     // the redirect succeeded.  We should either rename this API, or add a new method, like
   2672     // -webView:didFinishClientRedirectForFrame:
   2673     m_client->dispatchDidCancelClientRedirect();
   2674 
   2675     if (!cancelWithLoadInProgress)
   2676         m_quickRedirectComing = false;
   2677 
   2678     m_sentRedirectNotification = false;
   2679 }
   2680 
   2681 void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireDate, bool lockBackForwardList)
   2682 {
   2683     m_client->dispatchWillPerformClientRedirect(url, seconds, fireDate);
   2684 
   2685     // Remember that we sent a redirect notification to the frame load delegate so that when we commit
   2686     // the next provisional load, we can send a corresponding -webView:didCancelClientRedirectForFrame:
   2687     m_sentRedirectNotification = true;
   2688 
   2689     // If a "quick" redirect comes in, we set a special mode so we treat the next
   2690     // load as part of the original navigation. If we don't have a document loader, we have
   2691     // no "original" load on which to base a redirect, so we treat the redirect as a normal load.
   2692     // Loads triggered by JavaScript form submissions never count as quick redirects.
   2693     m_quickRedirectComing = lockBackForwardList && m_documentLoader && !m_isExecutingJavaScriptFormAction;
   2694 }
   2695 
   2696 bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
   2697 {
   2698 #if ENABLE(WML)
   2699     // All WML decks are supposed to be reloaded, even within the same URL fragment
   2700     if (frameContainsWMLContent(m_frame))
   2701         return true;
   2702 #endif
   2703 
   2704     // This function implements the rule: "Don't reload if navigating by fragment within
   2705     // the same URL, but do reload if going to a new URL or to the same URL with no
   2706     // fragment identifier at all."
   2707     if (!destinationURL.hasFragmentIdentifier())
   2708         return true;
   2709     return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
   2710 }
   2711 
   2712 void FrameLoader::closeOldDataSources()
   2713 {
   2714     // FIXME: Is it important for this traversal to be postorder instead of preorder?
   2715     // If so, add helpers for postorder traversal, and use them. If not, then lets not
   2716     // use a recursive algorithm here.
   2717     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   2718         child->loader()->closeOldDataSources();
   2719 
   2720     if (m_documentLoader)
   2721         m_client->dispatchWillClose();
   2722 
   2723     m_client->setMainFrameDocumentReady(false); // stop giving out the actual DOMDocument to observers
   2724 }
   2725 
   2726 void FrameLoader::open(CachedPage& cachedPage)
   2727 {
   2728     ASSERT(!m_frame->tree()->parent());
   2729     ASSERT(m_frame->page());
   2730     ASSERT(m_frame->page()->mainFrame() == m_frame);
   2731 
   2732     m_frame->redirectScheduler()->cancel();
   2733 
   2734     // We still have to close the previous part page.
   2735     closeURL();
   2736 
   2737     // Delete old status bar messages (if it _was_ activated on last URL).
   2738     if (m_frame->script()->canExecuteScripts()) {
   2739         m_frame->setJSStatusBarText(String());
   2740         m_frame->setJSDefaultStatusBarText(String());
   2741     }
   2742 
   2743     cachedPage.restore(m_frame->page());
   2744 
   2745     checkCompleted();
   2746 }
   2747 
   2748 void FrameLoader::open(CachedFrameBase& cachedFrame)
   2749 {
   2750     m_isComplete = false;
   2751 
   2752     // Don't re-emit the load event.
   2753     m_didCallImplicitClose = true;
   2754 
   2755     KURL url = cachedFrame.url();
   2756 
   2757     if (url.protocolInHTTPFamily() && !url.host().isEmpty() && url.path().isEmpty())
   2758         url.setPath("/");
   2759 
   2760     m_URL = url;
   2761     m_workingURL = url;
   2762 
   2763     started();
   2764     clear(true, true, cachedFrame.isMainFrame());
   2765 
   2766     Document* document = cachedFrame.document();
   2767     ASSERT(document);
   2768     document->setInPageCache(false);
   2769 
   2770     m_needsClear = true;
   2771     m_isComplete = false;
   2772     m_didCallImplicitClose = false;
   2773     m_outgoingReferrer = url.string();
   2774 
   2775     FrameView* view = cachedFrame.view();
   2776 
   2777     // When navigating to a CachedFrame its FrameView should never be null.  If it is we'll crash in creative ways downstream.
   2778     ASSERT(view);
   2779     view->setWasScrolledByUser(false);
   2780 
   2781     // Use the current ScrollView's frame rect.
   2782     if (m_frame->view())
   2783         view->setFrameRect(m_frame->view()->frameRect());
   2784     m_frame->setView(view);
   2785 
   2786     m_frame->setDocument(document);
   2787     m_frame->setDOMWindow(cachedFrame.domWindow());
   2788     m_frame->domWindow()->setURL(document->url());
   2789     m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
   2790 
   2791     m_decoder = document->decoder();
   2792 
   2793     updateFirstPartyForCookies();
   2794 
   2795     cachedFrame.restore();
   2796 }
   2797 
   2798 bool FrameLoader::isStopping() const
   2799 {
   2800     return activeDocumentLoader()->isStopping();
   2801 }
   2802 
   2803 void FrameLoader::finishedLoading()
   2804 {
   2805     // Retain because the stop may release the last reference to it.
   2806     RefPtr<Frame> protect(m_frame);
   2807 
   2808     RefPtr<DocumentLoader> dl = activeDocumentLoader();
   2809     dl->finishedLoading();
   2810     if (!dl->mainDocumentError().isNull() || !dl->frameLoader())
   2811         return;
   2812     dl->setPrimaryLoadComplete(true);
   2813     m_client->dispatchDidLoadMainResource(dl.get());
   2814     checkLoadComplete();
   2815 }
   2816 
   2817 bool FrameLoader::isHostedByObjectElement() const
   2818 {
   2819     HTMLFrameOwnerElement* owner = m_frame->ownerElement();
   2820     return owner && owner->hasTagName(objectTag);
   2821 }
   2822 
   2823 bool FrameLoader::isLoadingMainFrame() const
   2824 {
   2825     Page* page = m_frame->page();
   2826     return page && m_frame == page->mainFrame();
   2827 }
   2828 
   2829 bool FrameLoader::canShowMIMEType(const String& MIMEType) const
   2830 {
   2831     return m_client->canShowMIMEType(MIMEType);
   2832 }
   2833 
   2834 bool FrameLoader::representationExistsForURLScheme(const String& URLScheme)
   2835 {
   2836     return m_client->representationExistsForURLScheme(URLScheme);
   2837 }
   2838 
   2839 String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
   2840 {
   2841     return m_client->generatedMIMETypeForURLScheme(URLScheme);
   2842 }
   2843 
   2844 void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
   2845 {
   2846     m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
   2847 }
   2848 
   2849 void FrameLoader::finishedLoadingDocument(DocumentLoader* loader)
   2850 {
   2851     // FIXME: Platforms shouldn't differ here!
   2852 #if PLATFORM(WIN) || PLATFORM(CHROMIUM) || defined(ANDROID)
   2853     if (m_creatingInitialEmptyDocument)
   2854         return;
   2855 #endif
   2856 
   2857 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
   2858     // If loading a webarchive, run through webarchive machinery
   2859     const String& responseMIMEType = loader->responseMIMEType();
   2860 
   2861     // FIXME: Mac's FrameLoaderClient::finishedLoading() method does work that is required even with Archive loads
   2862     // so we still need to call it.  Other platforms should only call finishLoading for non-archive loads
   2863     // That work should be factored out so this #ifdef can be removed
   2864 #if PLATFORM(MAC)
   2865     m_client->finishedLoading(loader);
   2866     if (!ArchiveFactory::isArchiveMimeType(responseMIMEType))
   2867         return;
   2868 #else
   2869     if (!ArchiveFactory::isArchiveMimeType(responseMIMEType)) {
   2870         m_client->finishedLoading(loader);
   2871         return;
   2872     }
   2873 #endif
   2874 
   2875     RefPtr<Archive> archive(ArchiveFactory::create(loader->mainResourceData().get(), responseMIMEType));
   2876     if (!archive)
   2877         return;
   2878 
   2879     loader->addAllArchiveResources(archive.get());
   2880 
   2881     ArchiveResource* mainResource = archive->mainResource();
   2882     loader->setParsedArchiveData(mainResource->data());
   2883 
   2884     m_responseMIMEType = mainResource->mimeType();
   2885 
   2886     closeURL();
   2887     didOpenURL(mainResource->url());
   2888 
   2889     String userChosenEncoding = documentLoader()->overrideEncoding();
   2890     bool encodingIsUserChosen = !userChosenEncoding.isNull();
   2891     setEncoding(encodingIsUserChosen ? userChosenEncoding : mainResource->textEncoding(), encodingIsUserChosen);
   2892 
   2893     ASSERT(m_frame->document());
   2894 
   2895     addData(mainResource->data()->data(), mainResource->data()->size());
   2896 #else
   2897     m_client->finishedLoading(loader);
   2898 #endif // ARCHIVE
   2899 }
   2900 
   2901 bool FrameLoader::isReplacing() const
   2902 {
   2903     return m_loadType == FrameLoadTypeReplace;
   2904 }
   2905 
   2906 void FrameLoader::setReplacing()
   2907 {
   2908     m_loadType = FrameLoadTypeReplace;
   2909 }
   2910 
   2911 void FrameLoader::revertToProvisional(DocumentLoader* loader)
   2912 {
   2913     m_client->revertToProvisionalState(loader);
   2914 }
   2915 
   2916 bool FrameLoader::subframeIsLoading() const
   2917 {
   2918     // It's most likely that the last added frame is the last to load so we walk backwards.
   2919     for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling()) {
   2920         FrameLoader* childLoader = child->loader();
   2921         DocumentLoader* documentLoader = childLoader->documentLoader();
   2922         if (documentLoader && documentLoader->isLoadingInAPISense())
   2923             return true;
   2924         documentLoader = childLoader->provisionalDocumentLoader();
   2925         if (documentLoader && documentLoader->isLoadingInAPISense())
   2926             return true;
   2927     }
   2928     return false;
   2929 }
   2930 
   2931 void FrameLoader::willChangeTitle(DocumentLoader* loader)
   2932 {
   2933     m_client->willChangeTitle(loader);
   2934 }
   2935 
   2936 FrameLoadType FrameLoader::loadType() const
   2937 {
   2938     return m_loadType;
   2939 }
   2940 
   2941 CachePolicy FrameLoader::subresourceCachePolicy() const
   2942 {
   2943     if (m_isComplete)
   2944         return CachePolicyVerify;
   2945 
   2946     if (m_loadType == FrameLoadTypeReloadFromOrigin)
   2947         return CachePolicyReload;
   2948 
   2949     if (Frame* parentFrame = m_frame->tree()->parent()) {
   2950         CachePolicy parentCachePolicy = parentFrame->loader()->subresourceCachePolicy();
   2951         if (parentCachePolicy != CachePolicyVerify)
   2952             return parentCachePolicy;
   2953     }
   2954 
   2955     // FIXME: POST documents are always Reloads, but their subresources should still be Revalidate.
   2956     // If we bring the CachePolicy.h and ResourceRequest cache policy enums in sync with each other and
   2957     // remember "Revalidate" in ResourceRequests, we can remove this "POST" check and return either "Reload"
   2958     // or "Revalidate" if the DocumentLoader was requested with either.
   2959     const ResourceRequest& request(documentLoader()->request());
   2960     if (request.cachePolicy() == ReloadIgnoringCacheData && !equalIgnoringCase(request.httpMethod(), "post"))
   2961         return CachePolicyRevalidate;
   2962 
   2963     if (m_loadType == FrameLoadTypeReload)
   2964         return CachePolicyRevalidate;
   2965 
   2966     if (request.cachePolicy() == ReturnCacheDataElseLoad)
   2967         return CachePolicyAllowStale;
   2968 
   2969     return CachePolicyVerify;
   2970 }
   2971 
   2972 void FrameLoader::checkLoadCompleteForThisFrame()
   2973 {
   2974     ASSERT(m_client->hasWebView());
   2975 
   2976     switch (m_state) {
   2977         case FrameStateProvisional: {
   2978             if (m_delegateIsHandlingProvisionalLoadError)
   2979                 return;
   2980 
   2981             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
   2982             if (!pdl)
   2983                 return;
   2984 
   2985             // If we've received any errors we may be stuck in the provisional state and actually complete.
   2986             const ResourceError& error = pdl->mainDocumentError();
   2987             if (error.isNull())
   2988                 return;
   2989 
   2990             // Check all children first.
   2991             RefPtr<HistoryItem> item;
   2992             if (Page* page = m_frame->page())
   2993                 if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame())
   2994                     item = history()->currentItem();
   2995 
   2996             bool shouldReset = true;
   2997             if (!(pdl->isLoadingInAPISense() && !pdl->isStopping())) {
   2998                 m_delegateIsHandlingProvisionalLoadError = true;
   2999                 m_client->dispatchDidFailProvisionalLoad(error);
   3000                 m_delegateIsHandlingProvisionalLoadError = false;
   3001 
   3002                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
   3003                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
   3004                 // stopAllLoaders instead of stopLoadingSubframes?
   3005                 stopLoadingSubframes();
   3006                 pdl->stopLoading();
   3007 
   3008                 // If we're in the middle of loading multipart data, we need to restore the document loader.
   3009                 if (isReplacing() && !m_documentLoader.get())
   3010                     setDocumentLoader(m_provisionalDocumentLoader.get());
   3011 
   3012                 // Finish resetting the load state, but only if another load hasn't been started by the
   3013                 // delegate callback.
   3014                 if (pdl == m_provisionalDocumentLoader)
   3015                     clearProvisionalLoad();
   3016                 else if (activeDocumentLoader()) {
   3017                     KURL unreachableURL = activeDocumentLoader()->unreachableURL();
   3018                     if (!unreachableURL.isEmpty() && unreachableURL == pdl->request().url())
   3019                         shouldReset = false;
   3020                 }
   3021             }
   3022             if (shouldReset && item)
   3023                 if (Page* page = m_frame->page()) {
   3024                     page->backForwardList()->goToItem(item.get());
   3025                     Settings* settings = m_frame->settings();
   3026                     page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : item.get());
   3027                 }
   3028             return;
   3029         }
   3030 
   3031         case FrameStateCommittedPage: {
   3032             DocumentLoader* dl = m_documentLoader.get();
   3033             if (!dl || (dl->isLoadingInAPISense() && !dl->isStopping()))
   3034                 return;
   3035 
   3036             markLoadComplete();
   3037 
   3038             // FIXME: Is this subsequent work important if we already navigated away?
   3039             // Maybe there are bugs because of that, or extra work we can skip because
   3040             // the new page is ready.
   3041 
   3042             m_client->forceLayoutForNonHTML();
   3043 
   3044             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
   3045             if (Page* page = m_frame->page())
   3046                 if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) && page->backForwardList())
   3047                     history()->restoreScrollPositionAndViewState();
   3048 
   3049             if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad)
   3050                 return;
   3051 
   3052             const ResourceError& error = dl->mainDocumentError();
   3053 #ifndef NDEBUG
   3054             m_didDispatchDidCommitLoad = false;
   3055 #endif
   3056             if (!error.isNull())
   3057                 m_client->dispatchDidFailLoad(error);
   3058             else
   3059                 m_client->dispatchDidFinishLoad();
   3060 
   3061             if (Page* page = m_frame->page())
   3062                 page->progress()->progressCompleted(m_frame);
   3063 
   3064 #ifdef ANDROID_INSTRUMENT
   3065             if (!m_frame->tree()->parent() && m_frame->document()->renderArena())
   3066                 android::TimeCounter::report(m_URL, cache()->getLiveSize(), cache()->getDeadSize(),
   3067                         m_frame->document()->renderArena()->reportPoolSize());
   3068 #endif
   3069             return;
   3070         }
   3071 
   3072         case FrameStateComplete:
   3073             frameLoadCompleted();
   3074             return;
   3075     }
   3076 
   3077     ASSERT_NOT_REACHED();
   3078 }
   3079 
   3080 void FrameLoader::continueLoadAfterWillSubmitForm()
   3081 {
   3082     if (!m_provisionalDocumentLoader)
   3083         return;
   3084 
   3085     // DocumentLoader calls back to our prepareForLoadStart
   3086     m_provisionalDocumentLoader->prepareForLoadStart();
   3087 
   3088     // The load might be cancelled inside of prepareForLoadStart(), nulling out the m_provisionalDocumentLoader,
   3089     // so we need to null check it again.
   3090     if (!m_provisionalDocumentLoader)
   3091         return;
   3092 
   3093     DocumentLoader* activeDocLoader = activeDocumentLoader();
   3094     if (activeDocLoader && activeDocLoader->isLoadingMainResource())
   3095         return;
   3096 
   3097     m_loadingFromCachedPage = false;
   3098 
   3099     unsigned long identifier = 0;
   3100 
   3101     if (Page* page = m_frame->page()) {
   3102         identifier = page->progress()->createUniqueIdentifier();
   3103         notifier()->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
   3104     }
   3105 
   3106     if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier))
   3107         m_provisionalDocumentLoader->updateLoading();
   3108 }
   3109 
   3110 void FrameLoader::didFirstLayout()
   3111 {
   3112     if (Page* page = m_frame->page())
   3113         if (isBackForwardLoadType(m_loadType) && page->backForwardList())
   3114             history()->restoreScrollPositionAndViewState();
   3115 
   3116     m_firstLayoutDone = true;
   3117     m_client->dispatchDidFirstLayout();
   3118 }
   3119 
   3120 void FrameLoader::didFirstVisuallyNonEmptyLayout()
   3121 {
   3122     m_client->dispatchDidFirstVisuallyNonEmptyLayout();
   3123 }
   3124 
   3125 void FrameLoader::frameLoadCompleted()
   3126 {
   3127     // Note: Can be called multiple times.
   3128 
   3129     m_client->frameLoadCompleted();
   3130 
   3131     history()->updateForFrameLoadCompleted();
   3132 
   3133     // After a canceled provisional load, firstLayoutDone is false.
   3134     // Reset it to true if we're displaying a page.
   3135     if (m_documentLoader)
   3136         m_firstLayoutDone = true;
   3137 }
   3138 
   3139 bool FrameLoader::firstLayoutDone() const
   3140 {
   3141     return m_firstLayoutDone;
   3142 }
   3143 
   3144 void FrameLoader::detachChildren()
   3145 {
   3146     // FIXME: Is it really necessary to do this in reverse order?
   3147     Frame* previous;
   3148     for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
   3149         previous = child->tree()->previousSibling();
   3150         child->loader()->detachFromParent();
   3151     }
   3152 }
   3153 
   3154 void FrameLoader::closeAndRemoveChild(Frame* child)
   3155 {
   3156     child->tree()->detachFromParent();
   3157 
   3158     child->setView(0);
   3159     if (child->ownerElement() && child->page())
   3160         child->page()->decrementFrameCount();
   3161     child->pageDestroyed();
   3162 
   3163     m_frame->tree()->removeChild(child);
   3164 }
   3165 
   3166 void FrameLoader::recursiveCheckLoadComplete()
   3167 {
   3168     Vector<RefPtr<Frame>, 10> frames;
   3169 
   3170     for (RefPtr<Frame> frame = m_frame->tree()->firstChild(); frame; frame = frame->tree()->nextSibling())
   3171         frames.append(frame);
   3172 
   3173     unsigned size = frames.size();
   3174     for (unsigned i = 0; i < size; i++)
   3175         frames[i]->loader()->recursiveCheckLoadComplete();
   3176 
   3177     checkLoadCompleteForThisFrame();
   3178 }
   3179 
   3180 // Called every time a resource is completely loaded, or an error is received.
   3181 void FrameLoader::checkLoadComplete()
   3182 {
   3183     ASSERT(m_client->hasWebView());
   3184 
   3185     m_shouldCallCheckLoadComplete = false;
   3186 
   3187     // FIXME: Always traversing the entire frame tree is a bit inefficient, but
   3188     // is currently needed in order to null out the previous history item for all frames.
   3189     if (Page* page = m_frame->page())
   3190         page->mainFrame()->loader()->recursiveCheckLoadComplete();
   3191 }
   3192 
   3193 int FrameLoader::numPendingOrLoadingRequests(bool recurse) const
   3194 {
   3195     if (!recurse)
   3196         return numRequests(m_frame->document());
   3197 
   3198     int count = 0;
   3199     for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame))
   3200         count += numRequests(frame->document());
   3201     return count;
   3202 }
   3203 
   3204 String FrameLoader::userAgent(const KURL& url) const
   3205 {
   3206     return m_client->userAgent(url);
   3207 }
   3208 
   3209 void FrameLoader::tokenizerProcessedData()
   3210 {
   3211     checkCompleted();
   3212 }
   3213 
   3214 void FrameLoader::handledOnloadEvents()
   3215 {
   3216     m_client->dispatchDidHandleOnloadEvents();
   3217 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   3218     if (documentLoader())
   3219         documentLoader()->applicationCacheHost()->stopDeferringEvents();
   3220 #endif
   3221 }
   3222 
   3223 void FrameLoader::frameDetached()
   3224 {
   3225     stopAllLoaders();
   3226     m_frame->document()->stopActiveDOMObjects();
   3227     detachFromParent();
   3228 }
   3229 
   3230 void FrameLoader::detachFromParent()
   3231 {
   3232     RefPtr<Frame> protect(m_frame);
   3233 
   3234     closeURL();
   3235     stopAllLoaders();
   3236     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
   3237     detachChildren();
   3238 
   3239 #if ENABLE(INSPECTOR)
   3240     if (Page* page = m_frame->page())
   3241         page->inspectorController()->frameDetachedFromParent(m_frame);
   3242 #endif
   3243 
   3244     detachViewsAndDocumentLoader();
   3245 
   3246     if (Frame* parent = m_frame->tree()->parent()) {
   3247         parent->loader()->closeAndRemoveChild(m_frame);
   3248         parent->loader()->scheduleCheckCompleted();
   3249     } else {
   3250         m_frame->setView(0);
   3251         m_frame->pageDestroyed();
   3252     }
   3253 }
   3254 
   3255 void FrameLoader::detachViewsAndDocumentLoader()
   3256 {
   3257     m_client->detachedFromParent2();
   3258     setDocumentLoader(0);
   3259     m_client->detachedFromParent3();
   3260 }
   3261 
   3262 void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
   3263 {
   3264     addExtraFieldsToRequest(request, m_loadType, false, false);
   3265 }
   3266 
   3267 void FrameLoader::addExtraFieldsToMainResourceRequest(ResourceRequest& request)
   3268 {
   3269     addExtraFieldsToRequest(request, m_loadType, true, false);
   3270 }
   3271 
   3272 void FrameLoader::addExtraFieldsToRequest(ResourceRequest& request, FrameLoadType loadType, bool mainResource, bool cookiePolicyURLFromRequest)
   3273 {
   3274     // Don't set the cookie policy URL if it's already been set.
   3275     // But make sure to set it on all requests, as it has significance beyond the cookie policy for all protocols (<rdar://problem/6616664>).
   3276     if (request.firstPartyForCookies().isEmpty()) {
   3277         if (mainResource && (isLoadingMainFrame() || cookiePolicyURLFromRequest))
   3278             request.setFirstPartyForCookies(request.url());
   3279         else if (Document* document = m_frame->document())
   3280             request.setFirstPartyForCookies(document->firstPartyForCookies());
   3281     }
   3282 
   3283     // The remaining modifications are only necessary for HTTP and HTTPS.
   3284     if (!request.url().isEmpty() && !request.url().protocolInHTTPFamily())
   3285         return;
   3286 
   3287     applyUserAgent(request);
   3288 
   3289     if (loadType == FrameLoadTypeReload) {
   3290         request.setCachePolicy(ReloadIgnoringCacheData);
   3291         request.setHTTPHeaderField("Cache-Control", "max-age=0");
   3292     } else if (loadType == FrameLoadTypeReloadFromOrigin) {
   3293         request.setCachePolicy(ReloadIgnoringCacheData);
   3294         request.setHTTPHeaderField("Cache-Control", "no-cache");
   3295         request.setHTTPHeaderField("Pragma", "no-cache");
   3296     } else if (isBackForwardLoadType(loadType) && !request.url().protocolIs("https"))
   3297         request.setCachePolicy(ReturnCacheDataElseLoad);
   3298 
   3299     if (mainResource)
   3300         request.setHTTPAccept(defaultAcceptHeader);
   3301 
   3302     // Make sure we send the Origin header.
   3303     addHTTPOriginIfNeeded(request, String());
   3304 
   3305     // Always try UTF-8. If that fails, try frame encoding (if any) and then the default.
   3306     // For a newly opened frame with an empty URL, encoding() should not be used, because this methods asks decoder, which uses ISO-8859-1.
   3307     Settings* settings = m_frame->settings();
   3308     request.setResponseContentDispositionEncodingFallbackArray("UTF-8", m_URL.isEmpty() ? m_encoding : encoding(), settings ? settings->defaultTextEncodingName() : String());
   3309 }
   3310 
   3311 void FrameLoader::addHTTPOriginIfNeeded(ResourceRequest& request, String origin)
   3312 {
   3313     if (!request.httpOrigin().isEmpty())
   3314         return;  // Request already has an Origin header.
   3315 
   3316     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
   3317     // For example, if an intranet page has a hyperlink to an external web
   3318     // site, we don't want to include the Origin of the request because it
   3319     // will leak the internal host name. Similar privacy concerns have lead
   3320     // to the widespread suppression of the Referer header at the network
   3321     // layer.
   3322     if (request.httpMethod() == "GET" || request.httpMethod() == "HEAD")
   3323         return;
   3324 
   3325     // For non-GET and non-HEAD methods, always send an Origin header so the
   3326     // server knows we support this feature.
   3327 
   3328     if (origin.isEmpty()) {
   3329         // If we don't know what origin header to attach, we attach the value
   3330         // for an empty origin.
   3331         origin = SecurityOrigin::createEmpty()->toString();
   3332     }
   3333 
   3334     request.setHTTPOrigin(origin);
   3335 }
   3336 
   3337 void FrameLoader::committedLoad(DocumentLoader* loader, const char* data, int length)
   3338 {
   3339 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
   3340     if (ArchiveFactory::isArchiveMimeType(loader->response().mimeType()))
   3341         return;
   3342 #endif
   3343     m_client->committedLoad(loader, data, length);
   3344 }
   3345 
   3346 #ifdef ANDROID_USER_GESTURE
   3347 void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState, bool userGesture)
   3348 #else
   3349 void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String& referrer, const String& frameName, bool lockHistory, FrameLoadType loadType, PassRefPtr<Event> event, PassRefPtr<FormState> prpFormState)
   3350 #endif
   3351 {
   3352     RefPtr<FormState> formState = prpFormState;
   3353 
   3354     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
   3355     // This prevents a potential bug which may cause a page with a form that uses itself
   3356     // as an action to be returned from the cache without submitting.
   3357 
   3358     // FIXME: Where's the code that implements what the comment above says?
   3359 
   3360     // Previously when this method was reached, the original FrameLoadRequest had been deconstructed to build a
   3361     // bunch of parameters that would come in here and then be built back up to a ResourceRequest.  In case
   3362     // any caller depends on the immutability of the original ResourceRequest, I'm rebuilding a ResourceRequest
   3363     // from scratch as it did all along.
   3364     const KURL& url = inRequest.url();
   3365     RefPtr<FormData> formData = inRequest.httpBody();
   3366     const String& contentType = inRequest.httpContentType();
   3367     String origin = inRequest.httpOrigin();
   3368 
   3369     ResourceRequest workingResourceRequest(url);
   3370 #ifdef ANDROID_USER_GESTURE
   3371     workingResourceRequest.setUserGesture(userGesture);
   3372 #endif
   3373 
   3374     if (!referrer.isEmpty())
   3375         workingResourceRequest.setHTTPReferrer(referrer);
   3376     workingResourceRequest.setHTTPOrigin(origin);
   3377     workingResourceRequest.setHTTPMethod("POST");
   3378     workingResourceRequest.setHTTPBody(formData);
   3379     workingResourceRequest.setHTTPContentType(contentType);
   3380     addExtraFieldsToRequest(workingResourceRequest, loadType, true, true);
   3381 
   3382     NavigationAction action(url, loadType, true, event);
   3383 
   3384     if (!frameName.isEmpty()) {
   3385         // The search for a target frame is done earlier in the case of form submission.
   3386         if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName))
   3387             targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
   3388         else
   3389             policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy, workingResourceRequest, formState.release(), frameName, this);
   3390     } else
   3391         loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
   3392 }
   3393 
   3394 unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data)
   3395 {
   3396     String referrer = m_outgoingReferrer;
   3397     if (SecurityOrigin::shouldHideReferrer(request.url(), referrer))
   3398         referrer = String();
   3399 
   3400     ResourceRequest initialRequest = request;
   3401     initialRequest.setTimeoutInterval(10);
   3402 
   3403     // Use the original request's cache policy for two reasons:
   3404     // 1. For POST requests, we mutate the cache policy for the main resource,
   3405     //    but we do not want this to apply to subresources
   3406     // 2. Delegates that modify the cache policy using willSendRequest: should
   3407     //    not affect any other resources. Such changes need to be done
   3408     //    per request.
   3409     if (initialRequest.isConditional())
   3410         initialRequest.setCachePolicy(ReloadIgnoringCacheData);
   3411     else
   3412         initialRequest.setCachePolicy(originalRequest().cachePolicy());
   3413 
   3414     if (!referrer.isEmpty())
   3415         initialRequest.setHTTPReferrer(referrer);
   3416     addHTTPOriginIfNeeded(initialRequest, outgoingOrigin());
   3417 
   3418     if (Page* page = m_frame->page())
   3419         initialRequest.setFirstPartyForCookies(page->mainFrame()->loader()->documentLoader()->request().url());
   3420     initialRequest.setHTTPUserAgent(client()->userAgent(request.url()));
   3421 
   3422     unsigned long identifier = 0;
   3423     ResourceRequest newRequest(initialRequest);
   3424     requestFromDelegate(newRequest, identifier, error);
   3425 
   3426     if (error.isNull()) {
   3427         ASSERT(!newRequest.isNull());
   3428 
   3429 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   3430         if (!documentLoader()->applicationCacheHost()->maybeLoadSynchronously(newRequest, error, response, data)) {
   3431 #endif
   3432             ResourceHandle::loadResourceSynchronously(newRequest, storedCredentials, error, response, data, m_frame);
   3433 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
   3434             documentLoader()->applicationCacheHost()->maybeLoadFallbackSynchronously(newRequest, error, response, data);
   3435         }
   3436 #endif
   3437     }
   3438 
   3439     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.size(), error);
   3440     return identifier;
   3441 }
   3442 
   3443 const ResourceRequest& FrameLoader::originalRequest() const
   3444 {
   3445     return activeDocumentLoader()->originalRequestCopy();
   3446 }
   3447 
   3448 void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isComplete)
   3449 {
   3450     // Retain because the stop may release the last reference to it.
   3451     RefPtr<Frame> protect(m_frame);
   3452 
   3453     RefPtr<DocumentLoader> loader = activeDocumentLoader();
   3454 
   3455     if (isComplete) {
   3456         // FIXME: Don't want to do this if an entirely new load is going, so should check
   3457         // that both data sources on the frame are either this or nil.
   3458         stop();
   3459         if (m_client->shouldFallBack(error))
   3460             handleFallbackContent();
   3461     }
   3462 
   3463     if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) {
   3464         if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url())
   3465             m_submittedFormURL = KURL();
   3466 
   3467         // We might have made a page cache item, but now we're bailing out due to an error before we ever
   3468         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
   3469         // so that the existing view (that wenever got far enough to replace) can continue being used.
   3470         history()->invalidateCurrentItemCachedPage();
   3471 
   3472         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
   3473         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
   3474         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
   3475         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
   3476         // has ended.
   3477         if (m_sentRedirectNotification)
   3478             clientRedirectCancelledOrFinished(false);
   3479     }
   3480 
   3481     loader->mainReceivedError(error, isComplete);
   3482 }
   3483 
   3484 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
   3485     const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue)
   3486 {
   3487     FrameLoader* loader = static_cast<FrameLoader*>(argument);
   3488     loader->continueFragmentScrollAfterNavigationPolicy(request, shouldContinue);
   3489 }
   3490 
   3491 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
   3492 {
   3493     m_quickRedirectComing = false;
   3494 
   3495     if (!shouldContinue)
   3496         return;
   3497 
   3498     bool isRedirect = m_quickRedirectComing || policyChecker()->loadType() == FrameLoadTypeRedirectWithLockedBackForwardList;
   3499     loadInSameDocument(request.url(), 0, !isRedirect);
   3500 }
   3501 
   3502 bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, FrameLoadType loadType, const KURL& url)
   3503 {
   3504     // Should we do anchor navigation within the existing content?
   3505 
   3506     // We don't do this if we are submitting a form, explicitly reloading,
   3507     // currently displaying a frameset, or if the URL does not have a fragment.
   3508     // These rules were originally based on what KHTML was doing in KHTMLPart::openURL.
   3509 
   3510     // FIXME: What about load types other than Standard and Reload?
   3511 
   3512     return !isFormSubmission
   3513         && loadType != FrameLoadTypeReload
   3514         && loadType != FrameLoadTypeReloadFromOrigin
   3515         && loadType != FrameLoadTypeSame
   3516         && !shouldReload(this->url(), url)
   3517         // We don't want to just scroll if a link from within a
   3518         // frameset is trying to reload the frameset into _top.
   3519         && !m_frame->document()->isFrameSet();
   3520 }
   3521 
   3522 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
   3523     const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
   3524 {
   3525     FrameLoader* loader = static_cast<FrameLoader*>(argument);
   3526     loader->continueLoadAfterNavigationPolicy(request, formState, shouldContinue);
   3527 }
   3528 
   3529 void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState> formState, bool shouldContinue)
   3530 {
   3531     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
   3532     // nil policyDataSource because loading the alternate page will have passed
   3533     // through this method already, nested; otherwise, policyDataSource should still be set.
   3534     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
   3535 
   3536     bool isTargetItem = history()->provisionalItem() ? history()->provisionalItem()->isTargetItem() : false;
   3537 
   3538     // Two reasons we can't continue:
   3539     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this
   3540     //       is the user responding Cancel to the form repost nag sheet.
   3541     //    2) User responded Cancel to an alert popped up by the before unload event handler.
   3542     // The "before unload" event handler runs only for the main frame.
   3543     bool canContinue = shouldContinue && (!isLoadingMainFrame() || m_frame->shouldClose());
   3544 
   3545     if (!canContinue) {
   3546         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we
   3547         // need to report that the client redirect was cancelled.
   3548         if (m_quickRedirectComing)
   3549             clientRedirectCancelledOrFinished(false);
   3550 
   3551         setPolicyDocumentLoader(0);
   3552 
   3553         // If the navigation request came from the back/forward menu, and we punt on it, we have the
   3554         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity,
   3555         // we only do this when punting a navigation for the target frame or top-level frame.
   3556         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(policyChecker()->loadType()))
   3557             if (Page* page = m_frame->page()) {
   3558                 Frame* mainFrame = page->mainFrame();
   3559                 if (HistoryItem* resetItem = mainFrame->loader()->history()->currentItem()) {
   3560                     page->backForwardList()->goToItem(resetItem);
   3561                     Settings* settings = m_frame->settings();
   3562                     page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : resetItem);
   3563                 }
   3564             }
   3565         return;
   3566     }
   3567 
   3568     FrameLoadType type = policyChecker()->loadType();
   3569     stopAllLoaders();
   3570 
   3571     // <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
   3572     // might detach the current FrameLoader, in which case we should bail on this newly defunct load.
   3573     if (!m_frame->page())
   3574         return;
   3575 
   3576 #if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR) && USE(JSC)
   3577     if (Page* page = m_frame->page()) {
   3578         if (page->mainFrame() == m_frame)
   3579             page->inspectorController()->resumeDebugger();
   3580     }
   3581 #endif
   3582 
   3583     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
   3584     m_loadType = type;
   3585     setState(FrameStateProvisional);
   3586 
   3587     setPolicyDocumentLoader(0);
   3588 
   3589     if (isBackForwardLoadType(type) && loadProvisionalItemFromCachedPage())
   3590         return;
   3591 
   3592     if (formState)
   3593         m_client->dispatchWillSubmitForm(&PolicyChecker::continueLoadAfterWillSubmitForm, formState);
   3594     else
   3595         continueLoadAfterWillSubmitForm();
   3596 }
   3597 
   3598 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
   3599     const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
   3600 {
   3601     FrameLoader* loader = static_cast<FrameLoader*>(argument);
   3602     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName, shouldContinue);
   3603 }
   3604 
   3605 void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& request,
   3606     PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
   3607 {
   3608     if (!shouldContinue)
   3609         return;
   3610 
   3611     RefPtr<Frame> frame = m_frame;
   3612     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage();
   3613     if (!mainFrame)
   3614         return;
   3615 
   3616     if (frameName != "_blank")
   3617         mainFrame->tree()->setName(frameName);
   3618 
   3619     mainFrame->page()->setOpenedByDOM();
   3620     mainFrame->loader()->m_client->dispatchShow();
   3621     if (!m_suppressOpenerInNewFrame)
   3622         mainFrame->loader()->setOpener(frame.get());
   3623     mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
   3624 }
   3625 
   3626 void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error)
   3627 {
   3628     ASSERT(!request.isNull());
   3629 
   3630     identifier = 0;
   3631     if (Page* page = m_frame->page()) {
   3632         identifier = page->progress()->createUniqueIdentifier();
   3633         notifier()->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request);
   3634     }
   3635 
   3636     ResourceRequest newRequest(request);
   3637     notifier()->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse());
   3638 
   3639     if (newRequest.isNull())
   3640         error = cancelledError(request);
   3641     else
   3642         error = ResourceError();
   3643 
   3644     request = newRequest;
   3645 }
   3646 
   3647 void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
   3648 {
   3649     Page* page = m_frame->page();
   3650     if (!page)
   3651         return;
   3652 
   3653 #if ENABLE(INSPECTOR)
   3654     page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), resource);
   3655 #endif
   3656 
   3657     if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
   3658         return;
   3659 
   3660     if (!page->areMemoryCacheClientCallsEnabled()) {
   3661         m_documentLoader->recordMemoryCacheLoadForFutureClientNotification(resource->url());
   3662         m_documentLoader->didTellClientAboutLoad(resource->url());
   3663         return;
   3664     }
   3665 
   3666     ResourceRequest request(resource->url());
   3667     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize())) {
   3668         m_documentLoader->didTellClientAboutLoad(resource->url());
   3669         return;
   3670     }
   3671 
   3672     unsigned long identifier;
   3673     ResourceError error;
   3674     requestFromDelegate(request, identifier, error);
   3675     notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), resource->encodedSize(), error);
   3676 }
   3677 
   3678 void FrameLoader::applyUserAgent(ResourceRequest& request)
   3679 {
   3680     String userAgent = client()->userAgent(request.url());
   3681     ASSERT(!userAgent.isNull());
   3682     request.setHTTPUserAgent(userAgent);
   3683 }
   3684 
   3685 bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, const KURL& url)
   3686 {
   3687     Frame* topFrame = m_frame->tree()->top();
   3688     if (m_frame == topFrame)
   3689         return false;
   3690 
   3691     if (equalIgnoringCase(content, "deny"))
   3692         return true;
   3693 
   3694     if (equalIgnoringCase(content, "sameorigin")) {
   3695         RefPtr<SecurityOrigin> origin = SecurityOrigin::create(url);
   3696         if (!origin->isSameSchemeHostPort(topFrame->document()->securityOrigin()))
   3697             return true;
   3698     }
   3699 
   3700     return false;
   3701 }
   3702 
   3703 bool FrameLoader::loadProvisionalItemFromCachedPage()
   3704 {
   3705     RefPtr<CachedPage> cachedPage = pageCache()->get(history()->provisionalItem());
   3706     if (!cachedPage || !cachedPage->document())
   3707         return false;
   3708 
   3709     DocumentLoader *provisionalLoader = provisionalDocumentLoader();
   3710     LOG(PageCache, "WebCorePageCache: FrameLoader %p loading provisional DocumentLoader %p with URL '%s' from CachedPage %p", this, provisionalLoader, provisionalLoader->url().string().utf8().data(), cachedPage.get());
   3711 
   3712     provisionalLoader->prepareForLoadStart();
   3713 
   3714     m_loadingFromCachedPage = true;
   3715 
   3716     provisionalLoader->setCommitted(true);
   3717     commitProvisionalLoad(cachedPage);
   3718 
   3719     return true;
   3720 }
   3721 
   3722 void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
   3723 {
   3724     if (!canCachePage() || item->isInPageCache())
   3725         return;
   3726 
   3727     pageHidden();
   3728 
   3729     if (Page* page = m_frame->page()) {
   3730         RefPtr<CachedPage> cachedPage = CachedPage::create(page);
   3731         pageCache()->add(item, cachedPage.release());
   3732     }
   3733 }
   3734 
   3735 void FrameLoader::pageHidden()
   3736 {
   3737     m_unloadEventBeingDispatched = true;
   3738     if (m_frame->domWindow())
   3739         m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, true), m_frame->document());
   3740     m_unloadEventBeingDispatched = false;
   3741 
   3742     // Send pagehide event for subframes as well
   3743     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   3744         child->loader()->pageHidden();
   3745 }
   3746 
   3747 bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
   3748 {
   3749     if (!history()->currentItem())
   3750         return false;
   3751     return url == history()->currentItem()->url() || url == history()->currentItem()->originalURL();
   3752 }
   3753 
   3754 void FrameLoader::checkDidPerformFirstNavigation()
   3755 {
   3756     Page* page = m_frame->page();
   3757     if (!page)
   3758         return;
   3759 
   3760     if (!m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) {
   3761         m_didPerformFirstNavigation = true;
   3762         m_client->didPerformFirstNavigation();
   3763     }
   3764 }
   3765 
   3766 Frame* FrameLoader::findFrameForNavigation(const AtomicString& name)
   3767 {
   3768     Frame* frame = m_frame->tree()->find(name);
   3769     if (!shouldAllowNavigation(frame))
   3770         return 0;
   3771     return frame;
   3772 }
   3773 
   3774 void FrameLoader::navigateWithinDocument(HistoryItem* item)
   3775 {
   3776     ASSERT(item->documentSequenceNumber() == history()->currentItem()->documentSequenceNumber());
   3777 
   3778     // Save user view state to the current history item here since we don't do a normal load.
   3779     // FIXME: Does form state need to be saved here too?
   3780     history()->saveScrollPositionAndViewStateToItem(history()->currentItem());
   3781     if (FrameView* view = m_frame->view())
   3782         view->setWasScrolledByUser(false);
   3783 
   3784     history()->setCurrentItem(item);
   3785 
   3786     // loadInSameDocument() actually changes the URL and notifies load delegates of a "fake" load
   3787     loadInSameDocument(item->url(), item->stateObject(), false);
   3788 
   3789     // Restore user view state from the current history item here since we don't do a normal load.
   3790     history()->restoreScrollPositionAndViewState();
   3791 }
   3792 
   3793 // FIXME: This function should really be split into a couple pieces, some of
   3794 // which should be methods of HistoryController and some of which should be
   3795 // methods of FrameLoader.
   3796 void FrameLoader::navigateToDifferentDocument(HistoryItem* item, FrameLoadType loadType)
   3797 {
   3798     // Remember this item so we can traverse any child items as child frames load
   3799     history()->setProvisionalItem(item);
   3800 
   3801     // Check if we'll be using the page cache.  We only use the page cache
   3802     // if one exists and it is less than _backForwardCacheExpirationInterval
   3803     // seconds old.  If the cache is expired it gets flushed here.
   3804     if (RefPtr<CachedPage> cachedPage = pageCache()->get(item)) {
   3805         // FIXME: 1800 should not be hardcoded, it should come from
   3806         // WebKitBackForwardCacheExpirationIntervalKey in WebKit.
   3807         // Or we should remove WebKitBackForwardCacheExpirationIntervalKey.
   3808         if (currentTime() - cachedPage->timeStamp() <= 1800) {
   3809             loadWithDocumentLoader(cachedPage->documentLoader(), loadType, 0);
   3810             return;
   3811         }
   3812 
   3813         LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", history()->provisionalItem()->url().string().ascii().data());
   3814         pageCache()->remove(item);
   3815     }
   3816 
   3817     KURL itemURL = item->url();
   3818     KURL itemOriginalURL = item->originalURL();
   3819     KURL currentURL;
   3820     if (documentLoader())
   3821         currentURL = documentLoader()->url();
   3822     RefPtr<FormData> formData = item->formData();
   3823 
   3824     bool addedExtraFields = false;
   3825     ResourceRequest request(itemURL);
   3826 
   3827     if (!item->referrer().isNull())
   3828         request.setHTTPReferrer(item->referrer());
   3829 
   3830     // If this was a repost that failed the page cache, we might try to repost the form.
   3831     NavigationAction action;
   3832     if (formData) {
   3833         formData->generateFiles(m_frame->page()->chrome()->client());
   3834 
   3835         request.setHTTPMethod("POST");
   3836         request.setHTTPBody(formData);
   3837         request.setHTTPContentType(item->formContentType());
   3838         RefPtr<SecurityOrigin> securityOrigin = SecurityOrigin::createFromString(item->referrer());
   3839         addHTTPOriginIfNeeded(request, securityOrigin->toString());
   3840 
   3841         // Make sure to add extra fields to the request after the Origin header is added for the FormData case.
   3842         // See https://bugs.webkit.org/show_bug.cgi?id=22194 for more discussion.
   3843         addExtraFieldsToRequest(request, m_loadType, true, formData);
   3844         addedExtraFields = true;
   3845 
   3846         // FIXME: Slight hack to test if the NSURL cache contains the page we're going to.
   3847         // We want to know this before talking to the policy delegate, since it affects whether
   3848         // we show the DoYouReallyWantToRepost nag.
   3849         //
   3850         // This trick has a small bug (3123893) where we might find a cache hit, but then
   3851         // have the item vanish when we try to use it in the ensuing nav.  This should be
   3852         // extremely rare, but in that case the user will get an error on the navigation.
   3853 
   3854         if (ResourceHandle::willLoadFromCache(request, m_frame))
   3855             action = NavigationAction(itemURL, loadType, false);
   3856         else {
   3857             request.setCachePolicy(ReloadIgnoringCacheData);
   3858             action = NavigationAction(itemURL, NavigationTypeFormResubmitted);
   3859         }
   3860     } else {
   3861         switch (loadType) {
   3862             case FrameLoadTypeReload:
   3863             case FrameLoadTypeReloadFromOrigin:
   3864                 request.setCachePolicy(ReloadIgnoringCacheData);
   3865                 break;
   3866             case FrameLoadTypeBack:
   3867             case FrameLoadTypeBackWMLDeckNotAccessible:
   3868             case FrameLoadTypeForward:
   3869             case FrameLoadTypeIndexedBackForward:
   3870                 if (!itemURL.protocolIs("https"))
   3871                     request.setCachePolicy(ReturnCacheDataElseLoad);
   3872                 break;
   3873             case FrameLoadTypeStandard:
   3874             case FrameLoadTypeRedirectWithLockedBackForwardList:
   3875                 break;
   3876             case FrameLoadTypeSame:
   3877             default:
   3878                 ASSERT_NOT_REACHED();
   3879         }
   3880 
   3881         action = NavigationAction(itemOriginalURL, loadType, false);
   3882     }
   3883 
   3884     if (!addedExtraFields)
   3885         addExtraFieldsToRequest(request, m_loadType, true, formData);
   3886 
   3887     loadWithNavigationAction(request, action, false, loadType, 0);
   3888 }
   3889 
   3890 // Loads content into this frame, as specified by history item
   3891 void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
   3892 {
   3893     // We do same-document navigation in the following cases:
   3894     // - The HistoryItem has a history state object
   3895     // - Navigating to an anchor within the page, with no form data stored on the target item or the current history entry,
   3896     //   and the URLs in the frame tree match the history item for fragment scrolling.
   3897     HistoryItem* currentItem = history()->currentItem();
   3898     bool sameDocumentNavigation = (!item->formData() && !(currentItem && currentItem->formData()) && history()->urlsMatchItem(item))
   3899                                   || (currentItem && item->documentSequenceNumber() == currentItem->documentSequenceNumber());
   3900 
   3901 #if ENABLE(WML)
   3902     // All WML decks should go through the real load mechanism, not the scroll-to-anchor code
   3903     // FIXME: Why do WML decks have this different behavior?
   3904     // Are WML decks incompatible with HTML5 pushState/replaceState which require inter-document history navigations?
   3905     // Should this new API be disabled for WML pages, or does WML need to update their mechanism to act like normal loads?
   3906     // If scroll-to-anchor navigations were broken for WML and required them to have different loading behavior, then
   3907     // state object loads are certainly also broken for them.
   3908     if (frameContainsWMLContent(m_frame))
   3909         sameDocumentNavigation = false;
   3910 #endif
   3911 
   3912     if (sameDocumentNavigation)
   3913         navigateWithinDocument(item);
   3914     else
   3915         navigateToDifferentDocument(item, loadType);
   3916 }
   3917 
   3918 void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
   3919 {
   3920     m_client->setMainDocumentError(loader, error);
   3921 }
   3922 
   3923 void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, const ResourceError&)
   3924 {
   3925     loader->setPrimaryLoadComplete(true);
   3926     m_client->dispatchDidLoadMainResource(activeDocumentLoader());
   3927     checkCompleted();
   3928     if (m_frame->page())
   3929         checkLoadComplete();
   3930 }
   3931 
   3932 void FrameLoader::mainReceivedError(const ResourceError& error, bool isComplete)
   3933 {
   3934     activeDocumentLoader()->mainReceivedError(error, isComplete);
   3935 }
   3936 
   3937 ResourceError FrameLoader::cancelledError(const ResourceRequest& request) const
   3938 {
   3939     ResourceError error = m_client->cancelledError(request);
   3940     error.setIsCancellation(true);
   3941     return error;
   3942 }
   3943 
   3944 ResourceError FrameLoader::blockedError(const ResourceRequest& request) const
   3945 {
   3946     return m_client->blockedError(request);
   3947 }
   3948 
   3949 ResourceError FrameLoader::cannotShowURLError(const ResourceRequest& request) const
   3950 {
   3951     return m_client->cannotShowURLError(request);
   3952 }
   3953 
   3954 ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& response) const
   3955 {
   3956     return m_client->fileDoesNotExistError(response);
   3957 }
   3958 
   3959 bool FrameLoader::shouldUseCredentialStorage(ResourceLoader* loader)
   3960 {
   3961     return m_client->shouldUseCredentialStorage(loader->documentLoader(), loader->identifier());
   3962 }
   3963 
   3964 void FrameLoader::setTitle(const String& title)
   3965 {
   3966     documentLoader()->setTitle(title);
   3967 }
   3968 
   3969 KURL FrameLoader::originalRequestURL() const
   3970 {
   3971     return activeDocumentLoader()->originalRequest().url();
   3972 }
   3973 
   3974 String FrameLoader::referrer() const
   3975 {
   3976     return documentLoader()->request().httpReferrer();
   3977 }
   3978 
   3979 void FrameLoader::dispatchDocumentElementAvailable()
   3980 {
   3981     m_frame->injectUserScripts(InjectAtDocumentStart);
   3982     m_client->documentElementAvailable();
   3983 }
   3984 
   3985 void FrameLoader::dispatchDidClearWindowObjectsInAllWorlds()
   3986 {
   3987     if (!m_frame->script()->canExecuteScripts())
   3988         return;
   3989 
   3990     Vector<DOMWrapperWorld*> worlds;
   3991     ScriptController::getAllWorlds(worlds);
   3992     for (size_t i = 0; i < worlds.size(); ++i)
   3993         dispatchDidClearWindowObjectInWorld(worlds[i]);
   3994 }
   3995 
   3996 void FrameLoader::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
   3997 {
   3998     if (!m_frame->script()->canExecuteScripts() || !m_frame->script()->existingWindowShell(world))
   3999         return;
   4000 
   4001     m_client->dispatchDidClearWindowObjectInWorld(world);
   4002 
   4003 #if ENABLE(INSPECTOR)
   4004     if (world != mainThreadNormalWorld())
   4005         return;
   4006 
   4007     if (Page* page = m_frame->page()) {
   4008         if (InspectorController* inspector = page->inspectorController())
   4009             inspector->inspectedWindowScriptObjectCleared(m_frame);
   4010         if (InspectorController* inspector = page->parentInspectorController())
   4011             inspector->windowScriptObjectAvailable();
   4012     }
   4013 #endif
   4014 }
   4015 
   4016 void FrameLoader::updateSandboxFlags()
   4017 {
   4018     SandboxFlags flags = SandboxNone;
   4019     if (Frame* parentFrame = m_frame->tree()->parent())
   4020         flags |= parentFrame->loader()->sandboxFlags();
   4021     if (HTMLFrameOwnerElement* ownerElement = m_frame->ownerElement())
   4022         flags |= ownerElement->sandboxFlags();
   4023 
   4024     if (m_sandboxFlags == flags)
   4025         return;
   4026 
   4027     m_sandboxFlags = flags;
   4028 
   4029     for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
   4030         child->loader()->updateSandboxFlags();
   4031 }
   4032 
   4033 bool FrameLoader::isDocumentSandboxed(SandboxFlags mask) const
   4034 {
   4035     return m_frame->document() && m_frame->document()->securityOrigin()->isSandboxed(mask);
   4036 }
   4037 
   4038 PassRefPtr<Widget> FrameLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const HashMap<String, String>& args)
   4039 {
   4040     String baseURLString;
   4041     String codeBaseURLString;
   4042     Vector<String> paramNames;
   4043     Vector<String> paramValues;
   4044     HashMap<String, String>::const_iterator end = args.end();
   4045     for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) {
   4046         if (equalIgnoringCase(it->first, "baseurl"))
   4047             baseURLString = it->second;
   4048         else if (equalIgnoringCase(it->first, "codebase"))
   4049             codeBaseURLString = it->second;
   4050         paramNames.append(it->first);
   4051         paramValues.append(it->second);
   4052     }
   4053 
   4054     if (!codeBaseURLString.isEmpty()) {
   4055         KURL codeBaseURL = completeURL(codeBaseURLString);
   4056         if (!SecurityOrigin::canLoad(codeBaseURL, String(), element->document())) {
   4057             FrameLoader::reportLocalLoadFailed(m_frame, codeBaseURL.string());
   4058             return 0;
   4059         }
   4060     }
   4061 
   4062     if (baseURLString.isEmpty())
   4063         baseURLString = m_frame->document()->baseURL().string();
   4064     KURL baseURL = completeURL(baseURLString);
   4065 
   4066     RefPtr<Widget> widget = m_client->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues);
   4067     if (!widget)
   4068         return 0;
   4069 
   4070     m_containsPlugIns = true;
   4071     return widget;
   4072 }
   4073 
   4074 void FrameLoader::didChangeTitle(DocumentLoader* loader)
   4075 {
   4076     m_client->didChangeTitle(loader);
   4077 
   4078     if (loader == m_documentLoader) {
   4079         // Must update the entries in the back-forward list too.
   4080         history()->setCurrentItemTitle(loader->title());
   4081         // This must go through the WebFrame because it has the right notion of the current b/f item.
   4082         m_client->setTitle(loader->title(), loader->urlForHistory());
   4083         m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
   4084         m_client->dispatchDidReceiveTitle(loader->title());
   4085     }
   4086 }
   4087 
   4088 void FrameLoader::dispatchDidCommitLoad()
   4089 {
   4090     if (m_creatingInitialEmptyDocument)
   4091         return;
   4092 
   4093 #ifndef NDEBUG
   4094     m_didDispatchDidCommitLoad = true;
   4095 #endif
   4096 
   4097     m_client->dispatchDidCommitLoad();
   4098 
   4099 #if ENABLE(INSPECTOR)
   4100     if (Page* page = m_frame->page())
   4101         page->inspectorController()->didCommitLoad(m_documentLoader.get());
   4102 #endif
   4103 }
   4104 
   4105 void FrameLoader::tellClientAboutPastMemoryCacheLoads()
   4106 {
   4107     ASSERT(m_frame->page());
   4108     ASSERT(m_frame->page()->areMemoryCacheClientCallsEnabled());
   4109 
   4110     if (!m_documentLoader)
   4111         return;
   4112 
   4113     Vector<String> pastLoads;
   4114     m_documentLoader->takeMemoryCacheLoadsForClientNotification(pastLoads);
   4115 
   4116     size_t size = pastLoads.size();
   4117     for (size_t i = 0; i < size; ++i) {
   4118         CachedResource* resource = cache()->resourceForURL(pastLoads[i]);
   4119 
   4120         // FIXME: These loads, loaded from cache, but now gone from the cache by the time
   4121         // Page::setMemoryCacheClientCallsEnabled(true) is called, will not be seen by the client.
   4122         // Consider if there's some efficient way of remembering enough to deliver this client call.
   4123         // We have the URL, but not the rest of the response or the length.
   4124         if (!resource)
   4125             continue;
   4126 
   4127         ResourceRequest request(resource->url());
   4128         m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, resource->response(), resource->encodedSize());
   4129     }
   4130 }
   4131 
   4132 bool FrameLoaderClient::hasHTMLView() const
   4133 {
   4134     return true;
   4135 }
   4136 
   4137 } // namespace WebCore
   4138