diff options
Diffstat (limited to 'WebCore/loader')
-rw-r--r-- | WebCore/loader/Cache.cpp | 6 | ||||
-rw-r--r-- | WebCore/loader/CachedResource.cpp | 6 | ||||
-rw-r--r-- | WebCore/loader/CachedResourceHandle.h | 13 | ||||
-rw-r--r-- | WebCore/loader/EmptyClients.h | 1 | ||||
-rw-r--r-- | WebCore/loader/FrameLoader.cpp | 977 | ||||
-rw-r--r-- | WebCore/loader/FrameLoader.h | 705 | ||||
-rw-r--r-- | WebCore/loader/FrameLoaderTypes.h | 5 | ||||
-rw-r--r-- | WebCore/loader/HistoryController.cpp | 627 | ||||
-rw-r--r-- | WebCore/loader/HistoryController.h | 95 | ||||
-rw-r--r-- | WebCore/loader/ImageLoader.cpp | 112 | ||||
-rw-r--r-- | WebCore/loader/ImageLoader.h | 9 | ||||
-rw-r--r-- | WebCore/loader/MainResourceLoader.cpp | 2 | ||||
-rw-r--r-- | WebCore/loader/PolicyCallback.h | 60 | ||||
-rw-r--r-- | WebCore/loader/PolicyChecker.h | 106 | ||||
-rw-r--r-- | WebCore/loader/RedirectScheduler.cpp | 17 | ||||
-rw-r--r-- | WebCore/loader/RedirectScheduler.h | 54 | ||||
-rw-r--r-- | WebCore/loader/ResourceLoadNotifier.cpp | 177 | ||||
-rw-r--r-- | WebCore/loader/ResourceLoadNotifier.h | 74 | ||||
-rw-r--r-- | WebCore/loader/ResourceLoader.cpp | 22 |
19 files changed, 1736 insertions, 1332 deletions
diff --git a/WebCore/loader/Cache.cpp b/WebCore/loader/Cache.cpp index 391790f..46fb068 100644 --- a/WebCore/loader/Cache.cpp +++ b/WebCore/loader/Cache.cpp @@ -275,6 +275,12 @@ void Cache::pruneLiveResources() // Destroy any decoded data in live objects that we can. // Start from the tail, since this is the least recently accessed of the objects. + + // The list might not be sorted by the m_lastDecodedAccessTime. The impact + // of this weaker invariant is minor as the below if statement to check the + // elapsedTime will evaluate to false as the currentTime will be a lot + // greater than the current->m_lastDecodedAccessTime. + // For more details see: https://bugs.webkit.org/show_bug.cgi?id=30209 CachedResource* current = m_liveDecodedResources.m_tail; while (current) { CachedResource* prev = current->m_prevInLiveResourcesList; diff --git a/WebCore/loader/CachedResource.cpp b/WebCore/loader/CachedResource.cpp index 43de633..f2f52b0 100644 --- a/WebCore/loader/CachedResource.cpp +++ b/WebCore/loader/CachedResource.cpp @@ -242,6 +242,12 @@ void CachedResource::setDecodedSize(unsigned size) cache()->insertInLRUList(this); // Insert into or remove from the live decoded list if necessary. + // When inserting into the LiveDecodedResourcesList it is possible + // that the m_lastDecodedAccessTime is still zero or smaller than + // the m_lastDecodedAccessTime of the current list head. This is a + // violation of the invariant that the list is to be kept sorted + // by access time. The weakening of the invariant does not pose + // a problem. For more details please see: https://bugs.webkit.org/show_bug.cgi?id=30209 if (m_decodedSize && !m_inLiveDecodedResourcesList && hasClients()) cache()->insertInLiveDecodedResourcesList(this); else if (!m_decodedSize && m_inLiveDecodedResourcesList) diff --git a/WebCore/loader/CachedResourceHandle.h b/WebCore/loader/CachedResourceHandle.h index 9d45b94..0956e0c 100644 --- a/WebCore/loader/CachedResourceHandle.h +++ b/WebCore/loader/CachedResourceHandle.h @@ -60,7 +60,7 @@ namespace WebCore { template <class R> class CachedResourceHandle : public CachedResourceHandleBase { public: CachedResourceHandle() { } - CachedResourceHandle(R* res) : CachedResourceHandleBase(res) { } + CachedResourceHandle(R* res); CachedResourceHandle(const CachedResourceHandle<R>& o) : CachedResourceHandleBase(o) { } R* get() const { return reinterpret_cast<R*>(CachedResourceHandleBase::get()); } @@ -71,6 +71,17 @@ namespace WebCore { bool operator==(const CachedResourceHandleBase& o) const { return get() == o.get(); } bool operator!=(const CachedResourceHandleBase& o) const { return get() != o.get(); } }; + + // Don't inline for winscw compiler to prevent the compiler agressively resolving + // the base class of R* when CachedResourceHandler<T>(R*) is inlined. The bug is + // reported at: https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812. + template <class R> +#if !COMPILER(WINSCW) + inline +#endif + CachedResourceHandle<R>::CachedResourceHandle(R* res) : CachedResourceHandleBase(res) + { + } template <class R, class RR> bool operator==(const CachedResourceHandle<R>& h, const RR* res) { diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h index d9e09fb..44fad72 100644 --- a/WebCore/loader/EmptyClients.h +++ b/WebCore/loader/EmptyClients.h @@ -493,6 +493,7 @@ class EmptyPluginHalterClient : public PluginHalterClient { public: virtual bool shouldHaltPlugin(Node*) const { return false; } + virtual bool enabled() const { return false; } }; } diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp index 071c0a7..4e6b776 100644 --- a/WebCore/loader/FrameLoader.cpp +++ b/WebCore/loader/FrameLoader.cpp @@ -2,6 +2,8 @@ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2008 Alp Toker <alp@atoker.com> + * Copyright (C) Research In Motion Limited 2009. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -57,6 +59,7 @@ #include "FrameLoaderClient.h" #include "FrameTree.h" #include "FrameView.h" +#include "HTMLAnchorElement.h" #include "HTMLAppletElement.h" #include "HTMLFormElement.h" #include "HTMLFrameElement.h" @@ -76,6 +79,7 @@ #include "PageTransitionEvent.h" #include "PlaceholderDocument.h" #include "PluginData.h" +#include "PluginDatabase.h" #include "PluginDocument.h" #include "ProgressTracker.h" #include "RenderPart.h" @@ -114,6 +118,7 @@ #include "SVGViewSpec.h" #endif +<<<<<<< HEAD:WebCore/loader/FrameLoader.cpp #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" #include "RenderArena.h" @@ -127,6 +132,8 @@ #define PAGE_CACHE_ACCEPTS_UNLOAD_HANDLERS #endif +======= +>>>>>>> webkit.org at r50258.:WebCore/loader/FrameLoader.cpp namespace WebCore { #if ENABLE(SVG) @@ -178,6 +185,8 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) : m_frame(frame) , m_client(client) , m_policyChecker(frame) + , m_history(frame) + , m_notifer(frame) , m_state(FrameStateCommittedPage) , m_loadType(FrameLoadTypeStandard) , m_delegateIsHandlingProvisionalLoadError(false) @@ -186,7 +195,6 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) , m_sentRedirectNotification(false) , m_inStopAllLoaders(false) , m_isExecutingJavaScriptFormAction(false) - , m_isRunningScript(false) , m_didCallImplicitClose(false) , m_wasUnloadEventEmitted(false) , m_unloadEventBeingDispatched(false) @@ -205,6 +213,7 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client) , m_committedFirstRealDocumentLoad(false) , m_didPerformFirstNavigation(false) , m_loadingFromCachedPage(false) + , m_suppressOpenerInNewFrame(false) #ifndef NDEBUG , m_didDispatchDidCommitLoad(false) #endif @@ -262,7 +271,7 @@ Frame* FrameLoader::createWindow(FrameLoader* frameLoaderForFrameLookup, const F Frame* frame = frameLoaderForFrameLookup->frame()->tree()->find(request.frameName()); if (frame && shouldAllowNavigation(frame)) { if (!request.resourceRequest().url().isEmpty()) - frame->loader()->loadFrameRequest(request, false, false, 0, 0); + frame->loader()->loadFrameRequest(request, false, false, 0, 0, SendReferrer); if (Page* page = frame->page()) page->chrome()->focus(); created = false; @@ -329,15 +338,17 @@ void FrameLoader::changeLocation(const KURL& url, const String& referrer, bool l request.setUserGesture(userGesture); #endif - if (executeIfJavaScriptURL(request.url(), userGesture)) + if (m_frame->script()->executeIfJavaScriptURL(request.url(), userGesture)) return; - urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture); + urlSelected(request, "_self", 0, lockHistory, lockBackForwardList, userGesture, SendReferrer); } -void FrameLoader::urlSelected(const ResourceRequest& request, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture) +void FrameLoader::urlSelected(const ResourceRequest& request, const String& passedTarget, PassRefPtr<Event> triggeringEvent, bool lockHistory, bool lockBackForwardList, bool userGesture, ReferrerPolicy referrerPolicy) { - if (executeIfJavaScriptURL(request.url(), userGesture, false)) + ASSERT(!m_suppressOpenerInNewFrame); + + if (m_frame->script()->executeIfJavaScriptURL(request.url(), userGesture, false)) return; String target = passedTarget; @@ -346,11 +357,15 @@ void FrameLoader::urlSelected(const ResourceRequest& request, const String& pass FrameLoadRequest frameRequest(request, target); - if (frameRequest.resourceRequest().httpReferrer().isEmpty()) + if (referrerPolicy == NoReferrer) + m_suppressOpenerInNewFrame = true; + else if (frameRequest.resourceRequest().httpReferrer().isEmpty()) frameRequest.resourceRequest().setHTTPReferrer(m_outgoingReferrer); addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin()); - loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0); + loadFrameRequest(frameRequest, lockHistory, lockBackForwardList, triggeringEvent, 0, referrerPolicy); + + m_suppressOpenerInNewFrame = false; } bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String& urlString, const AtomicString& frameName) @@ -374,7 +389,7 @@ bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String return false; if (!scriptURL.isEmpty()) - frame->loader()->executeIfJavaScriptURL(scriptURL); + frame->script()->executeIfJavaScriptURL(scriptURL); return true; } @@ -446,7 +461,7 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F if (protocolIsJavaScript(u)) { m_isExecutingJavaScriptFormAction = true; - executeIfJavaScriptURL(u, false, false); + m_frame->script()->executeIfJavaScriptURL(u, false, false); m_isExecutingJavaScriptFormAction = false; return; } @@ -533,8 +548,14 @@ void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolic } // Dispatching the unload event could have made m_frame->document() null. - if (m_frame->document() && !m_frame->document()->inPageCache()) - m_frame->document()->removeAllEventListeners(); + if (m_frame->document() && !m_frame->document()->inPageCache()) { + // Don't remove event listeners from a transitional empty document (see bug 28716 for more information). + bool keepEventListeners = m_isDisplayingInitialEmptyDocument && m_provisionalDocumentLoader + && m_frame->document()->securityOrigin()->isSecureTransitionTo(m_provisionalDocumentLoader->url()); + + if (!keepEventListeners) + m_frame->document()->removeAllEventListeners(); + } } m_isComplete = true; // to avoid calling completed() in finishedParsing() @@ -581,7 +602,7 @@ void FrameLoader::stop() bool FrameLoader::closeURL() { - saveDocumentState(); + history()->saveDocumentState(); // Should only send the pagehide event here if the current document exists and has not been placed in the page cache. Document* currentDocument = m_frame->document(); @@ -624,7 +645,6 @@ bool FrameLoader::didOpenURL(const KURL& url) m_frame->redirectScheduler()->cancel(); m_frame->editor()->clearLastEditCommand(); - closeURL(); m_isComplete = false; m_isLoadingMainResource = true; @@ -664,62 +684,6 @@ void FrameLoader::didExplicitOpen() m_URL = m_frame->document()->url(); } -bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool replaceDocument) -{ - if (!protocolIsJavaScript(url)) - return false; - - if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed()) - return true; - - const int javascriptSchemeLength = sizeof("javascript:") - 1; - - String script = url.string().substring(javascriptSchemeLength); - ScriptValue result; - if (m_frame->script()->xssAuditor()->canEvaluateJavaScriptURL(script)) - result = executeScript(decodeURLEscapeSequences(script), userGesture); - - String scriptResult; - if (!result.getString(scriptResult)) - return true; - - SecurityOrigin* currentSecurityOrigin = m_frame->document()->securityOrigin(); - - // FIXME: We should always replace the document, but doing so - // synchronously can cause crashes: - // http://bugs.webkit.org/show_bug.cgi?id=16782 - if (replaceDocument) { - stopAllLoaders(); - begin(m_URL, true, currentSecurityOrigin); - write(scriptResult); - end(); - } - - return true; -} - -ScriptValue FrameLoader::executeScript(const String& script, bool forceUserGesture) -{ - return executeScript(ScriptSourceCode(script, forceUserGesture ? KURL() : m_URL)); -} - -ScriptValue FrameLoader::executeScript(const ScriptSourceCode& sourceCode) -{ - if (!m_frame->script()->isEnabled() || m_frame->script()->isPaused()) - return ScriptValue(); - - bool wasRunningScript = m_isRunningScript; - m_isRunningScript = true; - - ScriptValue result = m_frame->script()->evaluate(sourceCode); - - if (!wasRunningScript) { - m_isRunningScript = false; - Document::updateStyleForAllDocuments(); - } - - return result; -} void FrameLoader::cancelAndClear() { @@ -732,6 +696,14 @@ void FrameLoader::cancelAndClear() m_frame->script()->updatePlatformScriptObjects(); } +void FrameLoader::replaceDocument(const String& html) +{ + stopAllLoaders(); + begin(m_URL, true, m_frame->document()->securityOrigin()); + write(html); + end(); +} + void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView) { m_frame->editor()->clear(); @@ -807,6 +779,8 @@ void FrameLoader::receivedFirstData() String url; if (!m_documentLoader) return; + if (m_frame->inViewSourceMode()) + return; if (!parseHTTPRefresh(m_documentLoader->response().httpHeaderField("Refresh"), false, delay, url)) return; @@ -895,7 +869,7 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin) document->parseDNSPrefetchControlHeader(dnsPrefetchControl); } - restoreDocumentState(); + history()->restoreDocumentState(); document->implicitOpen(); @@ -1082,52 +1056,6 @@ void FrameLoader::commitIconURLToIconDatabase(const KURL& icon) iconDatabase()->setIconURLForPageURL(icon.string(), originalRequestURL().string()); } -void FrameLoader::restoreDocumentState() -{ - Document* doc = m_frame->document(); - - HistoryItem* itemToRestore = 0; - - switch (loadType()) { - case FrameLoadTypeReload: - case FrameLoadTypeReloadFromOrigin: - case FrameLoadTypeSame: - case FrameLoadTypeReplace: - break; - case FrameLoadTypeBack: - case FrameLoadTypeBackWMLDeckNotAccessible: - case FrameLoadTypeForward: - case FrameLoadTypeIndexedBackForward: - case FrameLoadTypeRedirectWithLockedBackForwardList: - case FrameLoadTypeStandard: - itemToRestore = m_currentHistoryItem.get(); - } - - if (!itemToRestore) - return; - - LOG(Loading, "WebCoreLoading %s: restoring form state from %p", m_frame->tree()->name().string().utf8().data(), itemToRestore); - doc->setStateForNewFormElements(itemToRestore->documentState()); -} - -void FrameLoader::gotoAnchor() -{ - // If our URL has no ref, then we have no place we need to jump to. - // OTOH If CSS target was set previously, we want to set it to 0, recalc - // and possibly repaint because :target pseudo class may have been - // set (see bug 11321). - if (!m_URL.hasFragmentIdentifier() && !m_frame->document()->cssTarget()) - return; - - String fragmentIdentifier = m_URL.fragmentIdentifier(); - if (gotoAnchor(fragmentIdentifier)) - return; - - // Try again after decoding the ref, based on the document's encoding. - if (m_decoder) - gotoAnchor(decodeURLEscapeSequences(fragmentIdentifier, m_decoder->encoding())); -} - void FrameLoader::finishedParsing() { if (m_creatingInitialEmptyDocument) @@ -1150,8 +1078,7 @@ void FrameLoader::finishedParsing() // Check if the scrollbars are really needed for the content. // If not, remove them, relayout, and repaint. m_frame->view()->restoreScrollbar(); - - gotoAnchor(); + m_frame->view()->scrollToFragment(m_URL); } void FrameLoader::loadDone() @@ -1275,7 +1202,7 @@ void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, { ASSERT(childFrame); - HistoryItem* parentItem = currentHistoryItem(); + HistoryItem* parentItem = history()->currentItem(); FrameLoadType loadType = this->loadType(); FrameLoadType childLoadType = FrameLoadTypeRedirectWithLockedBackForwardList; @@ -1291,7 +1218,7 @@ void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, // this is needed is Radar 3213556. workingURL = KURL(ParsedURLString, childItem->originalURLString()); childLoadType = loadType; - childFrame->loader()->m_provisionalHistoryItem = childItem; + childFrame->loader()->history()->setProvisionalItem(childItem); } } @@ -1342,6 +1269,7 @@ String FrameLoader::encoding() const return settings ? settings->defaultTextEncodingName() : String(); } +<<<<<<< HEAD:WebCore/loader/FrameLoader.cpp bool FrameLoader::gotoAnchor(const String& name) { ASSERT(m_frame->document()); @@ -1399,6 +1327,8 @@ bool FrameLoader::gotoAnchor(const String& name) return true; } +======= +>>>>>>> webkit.org at r50258.:WebCore/loader/FrameLoader.cpp bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const AtomicString& frameName, const String& mimeType, const Vector<String>& paramNames, const Vector<String>& paramValues) { @@ -1453,6 +1383,30 @@ bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool return objectType == ObjectContentNone || objectType == ObjectContentNetscapePlugin || objectType == ObjectContentOtherPlugin; } +ObjectContentType FrameLoader::defaultObjectContentType(const KURL& url, const String& mimeTypeIn) +{ + String mimeType = mimeTypeIn; + // We don't use MIMETypeRegistry::getMIMETypeForPath() because it returns "application/octet-stream" upon failure + if (mimeType.isEmpty()) + mimeType = MIMETypeRegistry::getMIMETypeForExtension(url.path().substring(url.path().reverseFind('.') + 1)); + + if (mimeType.isEmpty()) + return ObjectContentFrame; // Go ahead and hope that we can display the content. + + if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType)) + return WebCore::ObjectContentImage; + +#if !PLATFORM(MAC) && !PLATFORM(CHROMIUM) // Mac has no PluginDatabase, nor does Chromium + if (PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) + return WebCore::ObjectContentNetscapePlugin; +#endif + + if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType)) + return WebCore::ObjectContentFrame; + + return WebCore::ObjectContentNone; +} + static HTMLPlugInElement* toPlugInElement(Node* node) { if (!node) @@ -1483,6 +1437,8 @@ bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String return false; } + checkIfRunInsecureContent(m_frame->document()->securityOrigin(), url); + widget = m_client->createPlugin(IntSize(renderer->contentWidth(), renderer->contentHeight()), element, url, paramNames, paramValues, mimeType, m_frame->document()->isPluginDocument() && !m_containsPlugIns); @@ -1521,6 +1477,10 @@ void FrameLoader::checkIfDisplayInsecureContent(SecurityOrigin* context, const K if (!isMixedContent(context, url)) return; + String message = String::format("The page at %s displayed insecure content from %s.\n", + m_URL.string().utf8().data(), url.string().utf8().data()); + m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String()); + m_client->didDisplayInsecureContent(); } @@ -1529,6 +1489,10 @@ void FrameLoader::checkIfRunInsecureContent(SecurityOrigin* context, const KURL& if (!isMixedContent(context, url)) return; + String message = String::format("The page at %s ran insecure content from %s.\n", + m_URL.string().utf8().data(), url.string().utf8().data()); + m_frame->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, message, 1, String()); + m_client->didRunInsecureContent(context); } @@ -1626,9 +1590,7 @@ bool FrameLoader::canCachePageContainingThisFrame() // the right NPObjects. See <rdar://problem/5197041> for more information. && !m_containsPlugIns && !m_URL.protocolIs("https") -#ifndef PAGE_CACHE_ACCEPTS_UNLOAD_HANDLERS && (!m_frame->domWindow() || !m_frame->domWindow()->hasEventListeners(eventNames().unloadEvent)) -#endif #if ENABLE(DATABASE) && !m_frame->document()->hasOpenDatabases() #endif @@ -1636,7 +1598,7 @@ bool FrameLoader::canCachePageContainingThisFrame() && !SharedWorkerRepository::hasSharedWorkers(m_frame->document()) #endif && !m_frame->document()->usingGeolocation() - && m_currentHistoryItem + && history()->currentItem() && !m_quickRedirectComing && !m_documentLoader->isLoadingInAPISense() && !m_documentLoader->isStopping() @@ -1773,10 +1735,8 @@ bool FrameLoader::logCanCacheFrameDecision(int indentLevel) { PCLOG(" -Frame contains plugins"); cannotCache = true; } if (m_URL.protocolIs("https")) { PCLOG(" -Frame is HTTPS"); cannotCache = true; } -#ifndef PAGE_CACHE_ACCEPTS_UNLOAD_HANDLERS if (m_frame->domWindow() && m_frame->domWindow()->hasEventListeners(eventNames().unloadEvent)) { PCLOG(" -Frame has an unload event listener"); cannotCache = true; } -#endif #if ENABLE(DATABASE) if (m_frame->document()->hasOpenDatabases()) { PCLOG(" -Frame has open database handles"); cannotCache = true; } @@ -1787,7 +1747,7 @@ bool FrameLoader::logCanCacheFrameDecision(int indentLevel) #endif if (m_frame->document()->usingGeolocation()) { PCLOG(" -Frame uses Geolocation"); cannotCache = true; } - if (!m_currentHistoryItem) + if (!history()->currentItem()) { PCLOG(" -No current history item"); cannotCache = true; } if (m_quickRedirectComing) { PCLOG(" -Quick redirect is coming"); cannotCache = true; } @@ -1865,12 +1825,13 @@ void FrameLoader::scrollToAnchor(const KURL& url) } m_URL = url; - updateHistoryForAnchorScroll(); + history()->updateForAnchorScroll(); // If we were in the autoscroll/panScroll mode we want to stop it before following the link to the anchor m_frame->eventHandler()->stopAutoscrollTimer(); started(); - gotoAnchor(); + if (FrameView* view = m_frame->view()) + view->scrollToFragment(m_URL); // It's important to model this as a load that starts and immediately finishes. // Otherwise, the parent frame may think we never finished loading. @@ -1886,10 +1847,13 @@ bool FrameLoader::isComplete() const void FrameLoader::completed() { RefPtr<Frame> protect(m_frame); - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) - child->redirectScheduler()->startTimer(); + + for (Frame* descendant = m_frame->tree()->traverseNext(m_frame); descendant; descendant = descendant->tree()->traverseNext(m_frame)) + descendant->redirectScheduler()->startTimer(); + if (Frame* parent = m_frame->tree()->parent()) parent->loader()->checkCompleted(); + if (m_frame->view()) m_frame->view()->maintainScrollPositionAtAnchor(0); } @@ -1941,7 +1905,7 @@ static bool isFeedWithNestedProtocolInHTTPFamily(const KURL& url) } void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHistory, bool lockBackForwardList, - PassRefPtr<Event> event, PassRefPtr<FormState> formState) + PassRefPtr<Event> event, PassRefPtr<FormState> formState, ReferrerPolicy referrerPolicy) { KURL url = request.resourceRequest().url(); @@ -1960,7 +1924,7 @@ void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHis } } - if (SecurityOrigin::shouldHideReferrer(url, referrer)) + if (SecurityOrigin::shouldHideReferrer(url, referrer) || referrerPolicy == NoReferrer) referrer = String(); FrameLoadType loadType; @@ -2182,6 +2146,13 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t if (loader->triggeringAction().isEmpty()) loader->setTriggeringAction(NavigationAction(newURL, policyChecker()->loadType(), isFormSubmission)); + if (Element* ownerElement = m_frame->document()->ownerElement()) { + if (!ownerElement->dispatchBeforeLoadEvent(loader->request().url().string())) { + continueLoadAfterNavigationPolicy(loader->request(), formState, false); + return; + } + } + policyChecker()->checkNavigationPolicy(loader->request(), loader, formState, callContinueLoadAfterNavigationPolicy, this); } @@ -2208,15 +2179,12 @@ void FrameLoader::receivedData(const char* data, int length) bool FrameLoader::willLoadMediaElementURL(KURL& url) { - if (!m_client->shouldLoadMediaElementURL(url)) - return false; - ResourceRequest request(url); unsigned long identifier; ResourceError error; requestFromDelegate(request, identifier, error); - sendRemainingDelegateMessages(identifier, ResourceResponse(url, String(), -1, String(), String()), -1, error); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, ResourceResponse(url, String(), -1, String(), String()), -1, error); url = request.url(); @@ -2532,7 +2500,7 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage) // Check to see if we need to cache the page we are navigating away from into the back/forward cache. // We are doing this here because we know for sure that a new page is about to be loaded. - cachePageForHistoryItem(m_currentHistoryItem.get()); + cachePageForHistoryItem(history()->currentItem()); if (m_loadType != FrameLoadTypeReplace) closeOldDataSources(); @@ -2566,7 +2534,7 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage) LOG(Loading, "WebCoreLoading %s: Finished committing provisional load to URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data()); if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect()) - updateHistoryForClientRedirect(); + history()->updateForClientRedirect(); if (m_loadingFromCachedPage) { m_frame->document()->documentDidBecomeActive(); @@ -2586,10 +2554,10 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage) // FIXME: If we get a resource with more than 2B bytes, this code won't do the right thing. // However, with today's computers and networking speeds, this won't happen in practice. // Could be an issue with a giant local file. - sendRemainingDelegateMessages(identifier, response, static_cast<int>(response.expectedContentLength()), error); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, static_cast<int>(response.expectedContentLength()), error); } - pageCache()->remove(m_currentHistoryItem.get()); + pageCache()->remove(history()->currentItem()); m_documentLoader->setPrimaryLoadComplete(true); @@ -2607,7 +2575,7 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) return; m_client->setCopiesOnScroll(); - updateHistoryForCommit(); + history()->updateForCommit(); // The call to closeURL() invokes the unload event handler, which can execute arbitrary // JavaScript. If the script initiates a new load, we need to abandon the current load, @@ -2639,7 +2607,7 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) case FrameLoadTypeIndexedBackForward: if (Page* page = m_frame->page()) if (page->backForwardList()) { - updateHistoryForBackForwardNavigation(); + history()->updateForBackForwardNavigation(); // Create a document view for this document, or used the cached view. if (cachedPage) { @@ -2657,12 +2625,12 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) case FrameLoadTypeReloadFromOrigin: case FrameLoadTypeSame: case FrameLoadTypeReplace: - updateHistoryForReload(); + history()->updateForReload(); m_client->transitionToCommittedForNewPage(); break; case FrameLoadTypeStandard: - updateHistoryForStandardLoad(); + history()->updateForStandardLoad(); #ifndef BUILDING_ON_TIGER // This code was originally added for a Leopard performance imporvement. We decided to // ifdef it to fix correctness issues on Tiger documented in <rdar://problem/5441823>. @@ -2673,7 +2641,7 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage) break; case FrameLoadTypeRedirectWithLockedBackForwardList: - updateHistoryForRedirectWithLockedBackForwardList(); + history()->updateForRedirectWithLockedBackForwardList(); m_client->transitionToCommittedForNewPage(); break; @@ -2922,6 +2890,8 @@ void FrameLoader::finishedLoadingDocument(DocumentLoader* loader) loader->setParsedArchiveData(mainResource->data()); m_responseMIMEType = mainResource->mimeType(); + + closeURL(); didOpenURL(mainResource->url()); String userChosenEncoding = documentLoader()->overrideEncoding(); @@ -3026,7 +2996,7 @@ void FrameLoader::checkLoadCompleteForThisFrame() RefPtr<HistoryItem> item; if (Page* page = m_frame->page()) if (isBackForwardLoadType(loadType()) && m_frame == page->mainFrame()) - item = m_currentHistoryItem; + item = history()->currentItem(); bool shouldReset = true; if (!(pdl->isLoadingInAPISense() && !pdl->isStopping())) { @@ -3075,7 +3045,7 @@ void FrameLoader::checkLoadCompleteForThisFrame() // If the user had a scroll point, scroll to it, overriding the anchor point if any. if (Page* page = m_frame->page()) if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload || m_loadType == FrameLoadTypeReloadFromOrigin) && page->backForwardList()) - restoreScrollPositionAndViewState(); + history()->restoreScrollPositionAndViewState(); if (m_creatingInitialEmptyDocument || !m_committedFirstRealDocumentLoad) return; @@ -3131,7 +3101,7 @@ void FrameLoader::continueLoadAfterWillSubmitForm() if (Page* page = m_frame->page()) { identifier = page->progress()->createUniqueIdentifier(); - dispatchAssignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest()); + notifier()->assignIdentifierToInitialRequest(identifier, m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest()); } if (!m_provisionalDocumentLoader->startLoadingMainResource(identifier)) @@ -3142,7 +3112,7 @@ void FrameLoader::didFirstLayout() { if (Page* page = m_frame->page()) if (isBackForwardLoadType(m_loadType) && page->backForwardList()) - restoreScrollPositionAndViewState(); + history()->restoreScrollPositionAndViewState(); m_firstLayoutDone = true; m_client->dispatchDidFirstLayout(); @@ -3159,9 +3129,7 @@ void FrameLoader::frameLoadCompleted() m_client->frameLoadCompleted(); - // Even if already complete, we might have set a previous item on a frame that - // didn't do any data loading on the past transaction. Make sure to clear these out. - m_previousHistoryItem = 0; + history()->updateForFrameLoadCompleted(); // After a canceled provisional load, firstLayoutDone is false. // Reset it to true if we're displaying a page. @@ -3262,7 +3230,7 @@ void FrameLoader::detachFromParent() closeURL(); stopAllLoaders(); - saveScrollPositionAndViewStateToItem(currentHistoryItem()); + history()->saveScrollPositionAndViewStateToItem(history()->currentItem()); detachChildren(); #if ENABLE(INSPECTOR) @@ -3457,49 +3425,9 @@ unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& requ } #endif } - - sendRemainingDelegateMessages(identifier, response, data.size(), error); - return identifier; -} - -void FrameLoader::assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest& clientRequest) -{ - return dispatchAssignIdentifierToInitialRequest(identifier, activeDocumentLoader(), clientRequest); -} - -void FrameLoader::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse) -{ - applyUserAgent(clientRequest); - dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse); -} - -void FrameLoader::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r) -{ - activeDocumentLoader()->addResponse(r); - - if (Page* page = m_frame->page()) - page->progress()->incrementProgress(loader->identifier(), r); - dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r); -} - -void FrameLoader::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived) -{ - if (Page* page = m_frame->page()) - page->progress()->incrementProgress(loader->identifier(), data, length); - dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived); -} - -void FrameLoader::didFailToLoad(ResourceLoader* loader, const ResourceError& error) -{ - if (Page* page = m_frame->page()) - page->progress()->completeProgress(loader->identifier()); - if (!error.isNull()) - m_client->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error); -} -void FrameLoader::didLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) -{ - m_client->dispatchDidLoadResourceByXMLHttpRequest(identifier, sourceString); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, response, data.size(), error); + return identifier; } const ResourceRequest& FrameLoader::originalRequest() const @@ -3513,7 +3441,7 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isC RefPtr<Frame> protect(m_frame); RefPtr<DocumentLoader> loader = activeDocumentLoader(); - + if (isComplete) { // FIXME: Don't want to do this if an entirely new load is going, so should check // that both data sources on the frame are either this or nil. @@ -3521,7 +3449,7 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isC if (m_client->shouldFallBack(error)) handleFallbackContent(); } - + if (m_state == FrameStateProvisional && m_provisionalDocumentLoader) { if (m_submittedFormURL == m_provisionalDocumentLoader->originalRequestCopy().url()) m_submittedFormURL = KURL(); @@ -3529,7 +3457,7 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isC // We might have made a page cache item, but now we're bailing out due to an error before we ever // transitioned to the new page (before WebFrameState == commit). The goal here is to restore any state // so that the existing view (that wenever got far enough to replace) can continue being used. - invalidateCurrentItemCachedPage(); + history()->invalidateCurrentItemCachedPage(); // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's // status has changed, if there was a redirect. The frame load delegate may have saved some state about @@ -3539,8 +3467,7 @@ void FrameLoader::receivedMainResourceError(const ResourceError& error, bool isC if (m_sentRedirectNotification) clientRedirectCancelledOrFinished(false); } - - + loader->mainReceivedError(error, isComplete); } @@ -3581,7 +3508,7 @@ void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequ // we have already saved away the scroll and doc state for the long slow load, // but it's not an obvious case. - addHistoryItemForFragmentScroll(); + history()->updateBackForwardListForFragmentScroll(); } scrollToAnchor(url); @@ -3630,7 +3557,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass // through this method already, nested; otherwise, policyDataSource should still be set. ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty()); - bool isTargetItem = m_provisionalHistoryItem ? m_provisionalHistoryItem->isTargetItem() : false; + bool isTargetItem = history()->provisionalItem() ? history()->provisionalItem()->isTargetItem() : false; // Two reasons we can't continue: // 1) Navigation policy delegate said we can't so request is nil. A primary case of this @@ -3653,7 +3580,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(policyChecker()->loadType())) if (Page* page = m_frame->page()) { Frame* mainFrame = page->mainFrame(); - if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get()) { + if (HistoryItem* resetItem = mainFrame->loader()->history()->currentItem()) { page->backForwardList()->goToItem(resetItem); Settings* settings = m_frame->settings(); page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : resetItem); @@ -3715,24 +3642,11 @@ void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& reques mainFrame->page()->setOpenedByDOM(); mainFrame->loader()->m_client->dispatchShow(); - mainFrame->loader()->setOpener(frame.get()); + if (!m_suppressOpenerInNewFrame) + mainFrame->loader()->setOpener(frame.get()); mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState); } -void FrameLoader::sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error) -{ - if (!response.isNull()) - dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response); - - if (length > 0) - dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length); - - if (error.isNull()) - dispatchDidFinishLoading(m_documentLoader.get(), identifier); - else - m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error); -} - void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& identifier, ResourceError& error) { ASSERT(!request.isNull()); @@ -3740,11 +3654,11 @@ void FrameLoader::requestFromDelegate(ResourceRequest& request, unsigned long& i identifier = 0; if (Page* page = m_frame->page()) { identifier = page->progress()->createUniqueIdentifier(); - dispatchAssignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request); + notifier()->assignIdentifierToInitialRequest(identifier, m_documentLoader.get(), request); } ResourceRequest newRequest(request); - dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse()); + notifier()->dispatchWillSendRequest(m_documentLoader.get(), identifier, newRequest, ResourceResponse()); if (newRequest.isNull()) error = cancelledError(request); @@ -3782,7 +3696,7 @@ void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource) unsigned long identifier; ResourceError error; requestFromDelegate(request, identifier, error); - sendRemainingDelegateMessages(identifier, resource->response(), resource->encodedSize(), error); + notifier()->sendRemainingDelegateMessages(m_documentLoader.get(), identifier, resource->response(), resource->encodedSize(), error); } void FrameLoader::applyUserAgent(ResourceRequest& request) @@ -3810,14 +3724,9 @@ bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, con return false; } -void FrameLoader::addHistoryItemForFragmentScroll() -{ - addBackForwardItemClippedAtTarget(false); -} - bool FrameLoader::loadProvisionalItemFromCachedPage() { - RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get()); + RefPtr<CachedPage> cachedPage = pageCache()->get(history()->provisionalItem()); if (!cachedPage || !cachedPage->document()) return false; @@ -3861,119 +3770,21 @@ void FrameLoader::pageHidden() bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const { - if (!m_currentHistoryItem) + if (!history()->currentItem()) return false; - return url == m_currentHistoryItem->url() || url == m_currentHistoryItem->originalURL(); -} - -PassRefPtr<HistoryItem> FrameLoader::createHistoryItem(bool useOriginal) -{ - DocumentLoader* docLoader = documentLoader(); - - KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL(); - - KURL url; - KURL originalURL; - - if (!unreachableURL.isEmpty()) { - url = unreachableURL; - originalURL = unreachableURL; - } else { - originalURL = docLoader ? docLoader->originalURL() : KURL(); - if (useOriginal) - url = originalURL; - else if (docLoader) - url = docLoader->requestURL(); - } - - LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data()); - - // Frames that have never successfully loaded any content - // may have no URL at all. Currently our history code can't - // deal with such things, so we nip that in the bud here. - // Later we may want to learn to live with nil for URL. - // See bug 3368236 and related bugs for more information. - if (url.isEmpty()) - url = blankURL(); - if (originalURL.isEmpty()) - originalURL = blankURL(); - - Frame* parentFrame = m_frame->tree()->parent(); - String parent = parentFrame ? parentFrame->tree()->name() : ""; - String title = docLoader ? docLoader->title() : ""; - - RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->name(), parent, title); - item->setOriginalURLString(originalURL.string()); - - if (!unreachableURL.isEmpty() || !docLoader || docLoader->response().httpStatusCode() >= 400) - item->setLastVisitWasFailure(true); - - // Save form state if this is a POST - if (docLoader) { - if (useOriginal) - item->setFormInfoFromRequest(docLoader->originalRequest()); - else - item->setFormInfoFromRequest(docLoader->request()); - } - - // Set the item for which we will save document state - m_previousHistoryItem = m_currentHistoryItem; - m_currentHistoryItem = item; - - return item.release(); + return url == history()->currentItem()->url() || url == history()->currentItem()->originalURL(); } -void FrameLoader::addBackForwardItemClippedAtTarget(bool doClip) +void FrameLoader::checkDidPerformFirstNavigation() { - // In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree. - // The item that was the target of the user's navigation is designated as the "targetItem". - // When this function is called with doClip=true we're able to create the whole tree except for the target's children, - // which will be loaded in the future. That part of the tree will be filled out as the child loads are committed. - Page* page = m_frame->page(); if (!page) return; - if (documentLoader()->urlForHistory().isEmpty()) - return; - - Frame* mainFrame = page->mainFrame(); - ASSERT(mainFrame); - FrameLoader* frameLoader = mainFrame->loader(); - - if (!frameLoader->m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) { - frameLoader->m_didPerformFirstNavigation = true; + if (!m_didPerformFirstNavigation && page->backForwardList()->entries().size() == 1) { + m_didPerformFirstNavigation = true; m_client->didPerformFirstNavigation(); } - - RefPtr<HistoryItem> item = frameLoader->createHistoryItemTree(m_frame, doClip); - LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), documentLoader()->url().string().ascii().data()); - page->backForwardList()->addItem(item); -} - -PassRefPtr<HistoryItem> FrameLoader::createHistoryItemTree(Frame* targetFrame, bool clipAtTarget) -{ - RefPtr<HistoryItem> bfItem = createHistoryItem(m_frame->tree()->parent() ? true : false); - if (m_previousHistoryItem) - saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get()); - if (!(clipAtTarget && m_frame == targetFrame)) { - // save frame state for items that aren't loading (khtml doesn't save those) - saveDocumentState(); - for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { - FrameLoader* childLoader = child->loader(); - bool hasChildLoaded = childLoader->frameHasLoaded(); - - // If the child is a frame corresponding to an <object> element that never loaded, - // we don't want to create a history item, because that causes fallback content - // to be ignored on reload. - - if (!(!hasChildLoaded && childLoader->isHostedByObjectElement())) - bfItem->addChildItem(childLoader->createHistoryItemTree(targetFrame, clipAtTarget)); - } - } - if (m_frame == targetFrame) - bfItem->setIsTargetItem(true); - return bfItem; } Frame* FrameLoader::findFrameForNavigation(const AtomicString& name) @@ -3984,100 +3795,10 @@ Frame* FrameLoader::findFrameForNavigation(const AtomicString& name) return frame; } -void FrameLoader::saveScrollPositionAndViewStateToItem(HistoryItem* item) -{ - if (!item || !m_frame->view()) - return; - - item->setScrollPoint(m_frame->view()->scrollPosition()); - // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client. - m_client->saveViewStateToItem(item); -} - -/* - There is a race condition between the layout and load completion that affects restoring the scroll position. - We try to restore the scroll position at both the first layout and upon load completion. - - 1) If first layout happens before the load completes, we want to restore the scroll position then so that the - first time we draw the page is already scrolled to the right place, instead of starting at the top and later - jumping down. It is possible that the old scroll position is past the part of the doc laid out so far, in - which case the restore silent fails and we will fix it in when we try to restore on doc completion. - 2) If the layout happens after the load completes, the attempt to restore at load completion time silently - fails. We then successfully restore it when the layout happens. -*/ -void FrameLoader::restoreScrollPositionAndViewState() -{ - if (!m_committedFirstRealDocumentLoad) - return; - - ASSERT(m_currentHistoryItem); - - // FIXME: As the ASSERT attests, it seems we should always have a currentItem here. - // One counterexample is <rdar://problem/4917290> - // For now, to cover this issue in release builds, there is no technical harm to returning - // early and from a user standpoint - as in the above radar - the previous page load failed - // so there *is* no scroll or view state to restore! - if (!m_currentHistoryItem) - return; - - // FIXME: It would be great to work out a way to put this code in WebCore instead of calling - // through to the client. It's currently used only for the PDF view on Mac. - m_client->restoreViewState(); - - if (FrameView* view = m_frame->view()) - if (!view->wasScrolledByUser()) - view->setScrollPosition(m_currentHistoryItem->scrollPoint()); -} - -void FrameLoader::invalidateCurrentItemCachedPage() -{ - // When we are pre-commit, the currentItem is where the pageCache data resides - CachedPage* cachedPage = pageCache()->get(m_currentHistoryItem.get()); - - // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach - // Somehow the PageState object is not properly updated, and is holding onto a stale document. - // Both Xcode and FileMaker see this crash, Safari does not. - - ASSERT(!cachedPage || cachedPage->document() == m_frame->document()); - if (cachedPage && cachedPage->document() == m_frame->document()) { - cachedPage->document()->setInPageCache(false); - cachedPage->clear(); - } - - if (cachedPage) - pageCache()->remove(m_currentHistoryItem.get()); -} - -void FrameLoader::saveDocumentState() -{ - if (m_creatingInitialEmptyDocument) - return; - - // For a standard page load, we will have a previous item set, which will be used to - // store the form state. However, in some cases we will have no previous item, and - // the current item is the right place to save the state. One example is when we - // detach a bunch of frames because we are navigating from a site with frames to - // another site. Another is when saving the frame state of a frame that is not the - // target of the current navigation (if we even decide to save with that granularity). - - // Because of previousItem's "masking" of currentItem for this purpose, it's important - // that previousItem be cleared at the end of a page transition. We leverage the - // checkLoadComplete recursion to achieve this goal. - - HistoryItem* item = m_previousHistoryItem ? m_previousHistoryItem.get() : m_currentHistoryItem.get(); - if (!item) - return; - - Document* document = m_frame->document(); - ASSERT(document); - - if (item->isCurrentDocument(document)) { - LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().string().utf8().data(), item); - item->setDocumentState(document->formElementsState()); - } -} - // Loads content into this frame, as specified by history item +// FIXME: This function should really be split into a couple pieces, some of +// which should be methods of HistoryController and some of which should be +// methods of FrameLoader. void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) { if (!m_frame->page()) @@ -4096,7 +3817,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) // check for all that as an additional optimization. // We also do not do anchor-style navigation if we're posting a form or navigating from // a page that was resulted from a form post. - bool shouldScroll = !formData && !(m_currentHistoryItem && m_currentHistoryItem->formData()) && urlsMatchItem(item); + bool shouldScroll = !formData && !(history()->currentItem() && history()->currentItem()->formData()) && history()->urlsMatchItem(item); #if ENABLE(WML) // All WML decks should go through the real load mechanism, not the scroll-to-anchor code @@ -4106,12 +3827,12 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) if (shouldScroll) { // Must do this maintenance here, since we don't go through a real page reload - saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get()); + history()->saveScrollPositionAndViewStateToItem(history()->currentItem()); if (FrameView* view = m_frame->view()) view->setWasScrolledByUser(false); - m_currentHistoryItem = item; + history()->setCurrentItem(item); // FIXME: Form state might need to be saved here too. @@ -4120,7 +3841,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) scrollToAnchor(item->url()); // must do this maintenance here, since we don't go through a real page reload - restoreScrollPositionAndViewState(); + history()->restoreScrollPositionAndViewState(); // Fake the URL change by updating the data source's request. This will no longer // be necessary if we do the better fix described above. @@ -4132,7 +3853,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) m_client->didFinishLoad(); } else { // Remember this item so we can traverse any child items as child frames load - m_provisionalHistoryItem = item; + history()->setProvisionalItem(item); bool inPageCache = false; @@ -4149,7 +3870,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) loadWithDocumentLoader(cachedPage->documentLoader(), loadType, 0); inPageCache = true; } else { - LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", m_provisionalHistoryItem->url().string().ascii().data()); + LOG(PageCache, "Not restoring page for %s from back/forward cache because cache entry has expired", history()->provisionalItem()->url().string().ascii().data()); pageCache()->remove(item); } } @@ -4224,322 +3945,6 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType) } } -// Walk the frame tree and ensure that the URLs match the URLs in the item. -bool FrameLoader::urlsMatchItem(HistoryItem* item) const -{ - const KURL& currentURL = documentLoader()->url(); - if (!equalIgnoringFragmentIdentifier(currentURL, item->url())) - return false; - - const HistoryItemVector& childItems = item->children(); - - unsigned size = childItems.size(); - for (unsigned i = 0; i < size; ++i) { - Frame* childFrame = m_frame->tree()->child(childItems[i]->target()); - if (childFrame && !childFrame->loader()->urlsMatchItem(childItems[i].get())) - return false; - } - - return true; -} - -// Main funnel for navigating to a previous location (back/forward, non-search snap-back) -// This includes recursion to handle loading into framesets properly -void FrameLoader::goToItem(HistoryItem* targetItem, FrameLoadType type) -{ - ASSERT(!m_frame->tree()->parent()); - - // shouldGoToHistoryItem is a private delegate method. This is needed to fix: - // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls - // Ultimately, history item navigations should go through the policy delegate. That's covered in: - // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate - Page* page = m_frame->page(); - if (!page) - return; - if (!m_client->shouldGoToHistoryItem(targetItem)) - return; - - // Set the BF cursor before commit, which lets the user quickly click back/forward again. - // - plus, it only makes sense for the top level of the operation through the frametree, - // as opposed to happening for some/one of the page commits that might happen soon - BackForwardList* bfList = page->backForwardList(); - HistoryItem* currentItem = bfList->currentItem(); - bfList->goToItem(targetItem); - Settings* settings = m_frame->settings(); - page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : targetItem); - recursiveGoToItem(targetItem, currentItem, type); -} - -// The general idea here is to traverse the frame tree and the item tree in parallel, -// tracking whether each frame already has the content the item requests. If there is -// a match (by URL), we just restore scroll position and recurse. Otherwise we must -// reload that frame, and all its kids. -void FrameLoader::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type) -{ - ASSERT(item); - ASSERT(fromItem); - - KURL itemURL = item->url(); - KURL currentURL; - if (documentLoader()) - currentURL = documentLoader()->url(); - - // Always reload the target frame of the item we're going to. This ensures that we will - // do -some- load for the transition, which means a proper notification will be posted - // to the app. - // The exact URL has to match, including fragment. We want to go through the _load - // method, even if to do a within-page navigation. - // The current frame tree and the frame tree snapshot in the item have to match. - if (!item->isTargetItem() && - itemURL == currentURL && - ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) && - childFramesMatchItem(item)) - { - // This content is good, so leave it alone and look for children that need reloading - // Save form state (works from currentItem, since prevItem is nil) - ASSERT(!m_previousHistoryItem); - saveDocumentState(); - saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get()); - - if (FrameView* view = m_frame->view()) - view->setWasScrolledByUser(false); - - m_currentHistoryItem = item; - - // Restore form state (works from currentItem) - restoreDocumentState(); - - // Restore the scroll position (we choose to do this rather than going back to the anchor point) - restoreScrollPositionAndViewState(); - - const HistoryItemVector& childItems = item->children(); - - int size = childItems.size(); - for (int i = 0; i < size; ++i) { - String childFrameName = childItems[i]->target(); - HistoryItem* fromChildItem = fromItem->childItemWithTarget(childFrameName); - ASSERT(fromChildItem || fromItem->isTargetItem()); - Frame* childFrame = m_frame->tree()->child(childFrameName); - ASSERT(childFrame); - childFrame->loader()->recursiveGoToItem(childItems[i].get(), fromChildItem, type); - } - } else { - loadItem(item, type); - } -} - -// helper method that determines whether the subframes described by the item's subitems -// match our own current frameset -bool FrameLoader::childFramesMatchItem(HistoryItem* item) const -{ - const HistoryItemVector& childItems = item->children(); - if (childItems.size() != m_frame->tree()->childCount()) - return false; - - unsigned size = childItems.size(); - for (unsigned i = 0; i < size; ++i) { - if (!m_frame->tree()->child(childItems[i]->target())) - return false; - } - - // Found matches for all item targets - return true; -} - -// There are 3 things you might think of as "history", all of which are handled by these functions. -// -// 1) Back/forward: The m_currentHistoryItem is part of this mechanism. -// 2) Global history: Handled by the client. -// 3) Visited links: Handled by the PageGroup. - -void FrameLoader::updateHistoryForStandardLoad() -{ - LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", documentLoader()->url().string().ascii().data()); - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = documentLoader()->urlForHistory(); - - if (!documentLoader()->isClientRedirect()) { - if (!historyURL.isEmpty()) { - addBackForwardItemClippedAtTarget(true); - if (!needPrivacy) { - m_client->updateGlobalHistory(); - m_documentLoader->setDidCreateGlobalHistoryEntry(true); - if (m_documentLoader->unreachableURL().isEmpty()) - m_client->updateGlobalHistoryRedirectLinks(); - } - if (Page* page = m_frame->page()) - page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForwardList()->currentItem()); - } - } else if (documentLoader()->unreachableURL().isEmpty() && m_currentHistoryItem) { - m_currentHistoryItem->setURL(documentLoader()->url()); - m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request()); - } - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - page->group().addVisitedLink(historyURL); - - if (!m_documentLoader->didCreateGlobalHistoryEntry() && documentLoader()->unreachableURL().isEmpty() && !url().isEmpty()) - m_client->updateGlobalHistoryRedirectLinks(); - } -} - -void FrameLoader::updateHistoryForClientRedirect() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for client redirect in frame %s", documentLoader()->title().utf8().data()); -#endif - - // Clear out form data so we don't try to restore it into the incoming page. Must happen after - // webcore has closed the URL and saved away the form state. - if (m_currentHistoryItem) { - m_currentHistoryItem->clearDocumentState(); - m_currentHistoryItem->clearScrollPoint(); - } - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = documentLoader()->urlForHistory(); - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - page->group().addVisitedLink(historyURL); - } -} - -void FrameLoader::updateHistoryForBackForwardNavigation() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", documentLoader()->title().utf8().data()); -#endif - - // Must grab the current scroll position before disturbing it - saveScrollPositionAndViewStateToItem(m_previousHistoryItem.get()); -} - -void FrameLoader::updateHistoryForReload() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for reload in frame %s", documentLoader()->title().utf8().data()); -#endif - - if (m_currentHistoryItem) { - pageCache()->remove(m_currentHistoryItem.get()); - - if (loadType() == FrameLoadTypeReload || loadType() == FrameLoadTypeReloadFromOrigin) - saveScrollPositionAndViewStateToItem(m_currentHistoryItem.get()); - - // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072 - if (documentLoader()->unreachableURL().isEmpty()) - m_currentHistoryItem->setURL(documentLoader()->requestURL()); - } -} - -void FrameLoader::updateHistoryForRedirectWithLockedBackForwardList() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for redirect load in frame %s", documentLoader()->title().utf8().data()); -#endif - - Settings* settings = m_frame->settings(); - bool needPrivacy = !settings || settings->privateBrowsingEnabled(); - const KURL& historyURL = documentLoader()->urlForHistory(); - - if (documentLoader()->isClientRedirect()) { - if (!m_currentHistoryItem && !m_frame->tree()->parent()) { - if (!historyURL.isEmpty()) { - addBackForwardItemClippedAtTarget(true); - if (!needPrivacy) { - m_client->updateGlobalHistory(); - m_documentLoader->setDidCreateGlobalHistoryEntry(true); - if (m_documentLoader->unreachableURL().isEmpty()) - m_client->updateGlobalHistoryRedirectLinks(); - } - if (Page* page = m_frame->page()) - page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForwardList()->currentItem()); - } - } - if (m_currentHistoryItem) { - m_currentHistoryItem->setURL(documentLoader()->url()); - m_currentHistoryItem->setFormInfoFromRequest(documentLoader()->request()); - } - } else { - Frame* parentFrame = m_frame->tree()->parent(); - if (parentFrame && parentFrame->loader()->m_currentHistoryItem) - parentFrame->loader()->m_currentHistoryItem->setChildItem(createHistoryItem(true)); - } - - if (!historyURL.isEmpty() && !needPrivacy) { - if (Page* page = m_frame->page()) - page->group().addVisitedLink(historyURL); - - if (!m_documentLoader->didCreateGlobalHistoryEntry() && documentLoader()->unreachableURL().isEmpty() && !url().isEmpty()) - m_client->updateGlobalHistoryRedirectLinks(); - } -} - -void FrameLoader::updateHistoryForCommit() -{ -#if !LOG_DISABLED - if (documentLoader()) - LOG(History, "WebCoreHistory: Updating History for commit in frame %s", documentLoader()->title().utf8().data()); -#endif - FrameLoadType type = loadType(); - if (isBackForwardLoadType(type) || - ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin) && !provisionalDocumentLoader()->unreachableURL().isEmpty())) { - // Once committed, we want to use current item for saving DocState, and - // the provisional item for restoring state. - // Note previousItem must be set before we close the URL, which will - // happen when the data source is made non-provisional below - m_previousHistoryItem = m_currentHistoryItem; - ASSERT(m_provisionalHistoryItem); - m_currentHistoryItem = m_provisionalHistoryItem; - m_provisionalHistoryItem = 0; - } -} - -void FrameLoader::updateHistoryForAnchorScroll() -{ - if (m_URL.isEmpty()) - return; - - Settings* settings = m_frame->settings(); - if (!settings || settings->privateBrowsingEnabled()) - return; - - Page* page = m_frame->page(); - if (!page) - return; - - page->group().addVisitedLink(m_URL); -} - -// Walk the frame tree, telling all frames to save their form state into their current -// history item. -void FrameLoader::saveDocumentAndScrollState() -{ - for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) { - frame->loader()->saveDocumentState(); - frame->loader()->saveScrollPositionAndViewStateToItem(frame->loader()->currentHistoryItem()); - } -} - -HistoryItem* FrameLoader::currentHistoryItem() -{ - return m_currentHistoryItem.get(); -} - -void FrameLoader::setCurrentHistoryItem(PassRefPtr<HistoryItem> item) -{ - m_currentHistoryItem = item; -} - void FrameLoader::setMainDocumentError(DocumentLoader* loader, const ResourceError& error) { m_client->setMainDocumentError(loader, error); @@ -4581,28 +3986,11 @@ ResourceError FrameLoader::fileDoesNotExistError(const ResourceResponse& respons return m_client->fileDoesNotExistError(response); } -void FrameLoader::didFinishLoad(ResourceLoader* loader) -{ - if (Page* page = m_frame->page()) - page->progress()->completeProgress(loader->identifier()); - dispatchDidFinishLoading(loader->documentLoader(), loader->identifier()); -} - bool FrameLoader::shouldUseCredentialStorage(ResourceLoader* loader) { return m_client->shouldUseCredentialStorage(loader->documentLoader(), loader->identifier()); } -void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) -{ - m_client->dispatchDidReceiveAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); -} - -void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) -{ - m_client->dispatchDidCancelAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); -} - void FrameLoader::setTitle(const String& title) { documentLoader()->setTitle(title); @@ -4626,7 +4014,8 @@ void FrameLoader::dispatchDocumentElementAvailable() void FrameLoader::dispatchWindowObjectAvailable() { - if (!m_frame->script()->isEnabled() || !m_frame->script()->haveWindowShell()) + // FIXME: should this be isolated-worlds-aware? + if (!m_frame->script()->isEnabled() || !m_frame->script()->existingWindowShell(mainThreadNormalWorld())) return; m_client->windowObjectCleared(); @@ -4683,8 +4072,7 @@ void FrameLoader::didChangeTitle(DocumentLoader* loader) if (loader == m_documentLoader) { // Must update the entries in the back-forward list too. - if (m_currentHistoryItem) - m_currentHistoryItem->setTitle(loader->title()); + history()->setCurrentItemTitle(loader->title()); // This must go through the WebFrame because it has the right notion of the current b/f item. m_client->setTitle(loader->title(), loader->urlForHistory()); m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument @@ -4709,63 +4097,6 @@ void FrameLoader::dispatchDidCommitLoad() #endif } -void FrameLoader::dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) -{ - m_client->assignIdentifierToInitialRequest(identifier, loader, request); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->identifierForInitialRequest(identifier, loader, request); -#endif -} - -void FrameLoader::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) -{ - StringImpl* oldRequestURL = request.url().string().impl(); - m_documentLoader->didTellClientAboutLoad(request.url()); - - m_client->dispatchWillSendRequest(loader, identifier, request, redirectResponse); - - // If the URL changed, then we want to put that new URL in the "did tell client" set too. - if (!request.isNull() && oldRequestURL != request.url().string().impl()) - m_documentLoader->didTellClientAboutLoad(request.url()); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->willSendRequest(loader, identifier, request, redirectResponse); -#endif -} - -void FrameLoader::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r) -{ - m_client->dispatchDidReceiveResponse(loader, identifier, r); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didReceiveResponse(loader, identifier, r); -#endif -} - -void FrameLoader::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length) -{ - m_client->dispatchDidReceiveContentLength(loader, identifier, length); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didReceiveContentLength(loader, identifier, length); -#endif -} - -void FrameLoader::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier) -{ - m_client->dispatchDidFinishLoading(loader, identifier); - -#if ENABLE(INSPECTOR) - if (Page* page = m_frame->page()) - page->inspectorController()->didFinishLoading(loader, identifier); -#endif -} - void FrameLoader::tellClientAboutPastMemoryCacheLoads() { ASSERT(m_frame->page()); diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h index 9ea3775..1323089 100644 --- a/WebCore/loader/FrameLoader.h +++ b/WebCore/loader/FrameLoader.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) Research In Motion Limited 2009. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,9 +33,11 @@ #include "CachePolicy.h" #include "FrameLoaderTypes.h" +#include "HistoryController.h" #include "PolicyCallback.h" #include "PolicyChecker.h" #include "RedirectScheduler.h" +#include "ResourceLoadNotifier.h" #include "ResourceRequest.h" #include "ThreadableLoader.h" #include "Timer.h" @@ -42,6 +45,7 @@ namespace WebCore { +<<<<<<< HEAD:WebCore/loader/FrameLoader.h #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size class Archive; #endif @@ -75,369 +79,369 @@ namespace WebCore { class SubstituteData; class TextResourceDecoder; class Widget; +======= +class Archive; +class AuthenticationChallenge; +class CachedFrameBase; +class CachedPage; +class CachedResource; +class Document; +class DocumentLoader; +class Event; +class FormData; +class FormState; +class Frame; +class FrameLoaderClient; +class HistoryItem; +class HTMLAppletElement; +class HTMLFormElement; +class HTMLFrameOwnerElement; +class IconLoader; +class IntSize; +class NavigationAction; +class RenderPart; +class ResourceError; +class ResourceLoader; +class ResourceResponse; +class ScriptSourceCode; +class ScriptString; +class ScriptValue; +class SecurityOrigin; +class SharedBuffer; +class SubstituteData; +class TextResourceDecoder; +class Widget; +>>>>>>> webkit.org at r50258.:WebCore/loader/FrameLoader.h + +struct FrameLoadRequest; +struct WindowFeatures; + +bool isBackForwardLoadType(FrameLoadType); + +class FrameLoader : public Noncopyable { +public: + FrameLoader(Frame*, FrameLoaderClient*); + ~FrameLoader(); + + void init(); + + Frame* frame() const { return m_frame; } + + PolicyChecker* policyChecker() const { return &m_policyChecker; } + HistoryController* history() const { return &m_history; } + ResourceLoadNotifier* notifier() const { return &m_notifer; } + + // FIXME: This is not cool, people. There are too many different functions that all start loads. + // We should aim to consolidate these into a smaller set of functions, and try to reuse more of + // the logic by extracting common code paths. + + void prepareForLoadStart(); + void setupForReplace(); + void setupForReplaceByMIMEType(const String& newMIMEType); + + void loadURLIntoChildFrame(const KURL&, const String& referer, Frame*); + + void loadFrameRequest(const FrameLoadRequest&, bool lockHistory, bool lockBackForwardList, // Called by submitForm, calls loadPostRequest and loadURL. + PassRefPtr<Event>, PassRefPtr<FormState>, ReferrerPolicy); + +<<<<<<< HEAD:WebCore/loader/FrameLoader.h + void load(const ResourceRequest&, bool lockHistory); // Called by WebFrame, calls load(ResourceRequest, SubstituteData). + void load(const ResourceRequest&, const SubstituteData&, bool lockHistory); // Called both by WebFrame and internally, calls load(DocumentLoader*). + void load(const ResourceRequest&, const String& frameName, bool lockHistory); // Called by WebPluginController. + +#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size + void loadArchive(PassRefPtr<Archive>); +#endif +======= + void load(const ResourceRequest&, bool lockHistory); // Called by WebFrame, calls load(ResourceRequest, SubstituteData). + void load(const ResourceRequest&, const SubstituteData&, bool lockHistory); // Called both by WebFrame and internally, calls load(DocumentLoader*). + void load(const ResourceRequest&, const String& frameName, bool lockHistory); // Called by WebPluginController. + + void loadArchive(PassRefPtr<Archive>); +>>>>>>> webkit.org at r50258.:WebCore/loader/FrameLoader.h + + static void reportLocalLoadFailed(Frame*, const String& url); - struct FrameLoadRequest; - struct WindowFeatures; + // Called by createWindow in JSDOMWindowBase.cpp, e.g. to fulfill a modal dialog creation + Frame* createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest&, const WindowFeatures&, bool& created); - bool isBackForwardLoadType(FrameLoadType); + unsigned long loadResourceSynchronously(const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data); - class FrameLoader : public Noncopyable { - public: - FrameLoader(Frame*, FrameLoaderClient*); - ~FrameLoader(); + bool canHandleRequest(const ResourceRequest&); - void init(); + // Also not cool. + void stopAllLoaders(DatabasePolicy = DatabasePolicyStop); + void stopForUserCancel(bool deferCheckLoadComplete = false); - Frame* frame() const { return m_frame; } + bool isLoadingMainResource() const { return m_isLoadingMainResource; } + bool isLoading() const; + bool frameHasLoaded() const; - PolicyChecker* policyChecker() { return &m_policyChecker; } + int numPendingOrLoadingRequests(bool recurse) const; + String referrer() const; + String outgoingReferrer() const; + String outgoingOrigin() const; - // FIXME: This is not cool, people. There are too many different functions that all start loads. - // We should aim to consolidate these into a smaller set of functions, and try to reuse more of - // the logic by extracting common code paths. + DocumentLoader* activeDocumentLoader() const; + DocumentLoader* documentLoader() const { return m_documentLoader.get(); } + DocumentLoader* policyDocumentLoader() const { return m_policyDocumentLoader.get(); } + DocumentLoader* provisionalDocumentLoader() const { return m_provisionalDocumentLoader.get(); } + FrameState state() const { return m_state; } + static double timeOfLastCompletedLoad(); - void prepareForLoadStart(); - void setupForReplace(); - void setupForReplaceByMIMEType(const String& newMIMEType); + bool shouldUseCredentialStorage(ResourceLoader*); + const ResourceRequest& originalRequest() const; + const ResourceRequest& initialRequest() const; + void receivedMainResourceError(const ResourceError&, bool isComplete); + void receivedData(const char*, int); - void loadURLIntoChildFrame(const KURL&, const String& referer, Frame*); + bool willLoadMediaElementURL(KURL&); - void loadFrameRequest(const FrameLoadRequest&, bool lockHistory, bool lockBackForwardList, // Called by submitForm, calls loadPostRequest and loadURL. - PassRefPtr<Event>, PassRefPtr<FormState>); + void handleFallbackContent(); + bool isStopping() const; - void load(const ResourceRequest&, bool lockHistory); // Called by WebFrame, calls load(ResourceRequest, SubstituteData). - void load(const ResourceRequest&, const SubstituteData&, bool lockHistory); // Called both by WebFrame and internally, calls load(DocumentLoader*). - void load(const ResourceRequest&, const String& frameName, bool lockHistory); // Called by WebPluginController. - -#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size - void loadArchive(PassRefPtr<Archive>); -#endif + void finishedLoading(); - static void reportLocalLoadFailed(Frame*, const String& url); + ResourceError cancelledError(const ResourceRequest&) const; + ResourceError fileDoesNotExistError(const ResourceResponse&) const; + ResourceError blockedError(const ResourceRequest&) const; + ResourceError cannotShowURLError(const ResourceRequest&) const; + ResourceError interruptionForPolicyChangeError(const ResourceRequest&); - // Called by createWindow in JSDOMWindowBase.cpp, e.g. to fulfill a modal dialog creation - Frame* createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest&, const WindowFeatures&, bool& created); + bool isHostedByObjectElement() const; + bool isLoadingMainFrame() const; + bool canShowMIMEType(const String& MIMEType) const; + bool representationExistsForURLScheme(const String& URLScheme); + String generatedMIMETypeForURLScheme(const String& URLScheme); - unsigned long loadResourceSynchronously(const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data); + void reload(bool endToEndReload = false); + void reloadWithOverrideEncoding(const String& overrideEncoding); - bool canHandleRequest(const ResourceRequest&); + void didReceiveServerRedirectForProvisionalLoadForFrame(); + void finishedLoadingDocument(DocumentLoader*); + void committedLoad(DocumentLoader*, const char*, int); + bool isReplacing() const; + void setReplacing(); + void revertToProvisional(DocumentLoader*); + void setMainDocumentError(DocumentLoader*, const ResourceError&); + void mainReceivedCompleteError(DocumentLoader*, const ResourceError&); + bool subframeIsLoading() const; + void willChangeTitle(DocumentLoader*); + void didChangeTitle(DocumentLoader*); - // Also not cool. - void stopAllLoaders(DatabasePolicy = DatabasePolicyStop); - void stopForUserCancel(bool deferCheckLoadComplete = false); + FrameLoadType loadType() const; + CachePolicy subresourceCachePolicy() const; - bool isLoadingMainResource() const { return m_isLoadingMainResource; } - bool isLoading() const; - bool frameHasLoaded() const; + void didFirstLayout(); + bool firstLayoutDone() const; - int numPendingOrLoadingRequests(bool recurse) const; - String referrer() const; - String outgoingReferrer() const; - String outgoingOrigin() const; + void didFirstVisuallyNonEmptyLayout(); - DocumentLoader* activeDocumentLoader() const; - DocumentLoader* documentLoader() const { return m_documentLoader.get(); } - DocumentLoader* policyDocumentLoader() const { return m_policyDocumentLoader.get(); } - DocumentLoader* provisionalDocumentLoader() const { return m_provisionalDocumentLoader.get(); } - FrameState state() const { return m_state; } - static double timeOfLastCompletedLoad(); - - bool shouldUseCredentialStorage(ResourceLoader*); - void didReceiveAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); - void didCancelAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); - - void assignIdentifierToInitialRequest(unsigned long identifier, const ResourceRequest&); - void willSendRequest(ResourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse); - void didReceiveResponse(ResourceLoader*, const ResourceResponse&); - void didReceiveData(ResourceLoader*, const char*, int, int lengthReceived); - void didFinishLoad(ResourceLoader*); - void didFailToLoad(ResourceLoader*, const ResourceError&); - void didLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString); - const ResourceRequest& originalRequest() const; - const ResourceRequest& initialRequest() const; - void receivedMainResourceError(const ResourceError&, bool isComplete); - void receivedData(const char*, int); - - bool willLoadMediaElementURL(KURL&); - - void handleFallbackContent(); - bool isStopping() const; - - void finishedLoading(); - - ResourceError cancelledError(const ResourceRequest&) const; - ResourceError fileDoesNotExistError(const ResourceResponse&) const; - ResourceError blockedError(const ResourceRequest&) const; - ResourceError cannotShowURLError(const ResourceRequest&) const; - ResourceError interruptionForPolicyChangeError(const ResourceRequest&); - - bool isHostedByObjectElement() const; - bool isLoadingMainFrame() const; - bool canShowMIMEType(const String& MIMEType) const; - bool representationExistsForURLScheme(const String& URLScheme); - String generatedMIMETypeForURLScheme(const String& URLScheme); - - void reload(bool endToEndReload = false); - void reloadWithOverrideEncoding(const String& overrideEncoding); - - void didReceiveServerRedirectForProvisionalLoadForFrame(); - void finishedLoadingDocument(DocumentLoader*); - void committedLoad(DocumentLoader*, const char*, int); - bool isReplacing() const; - void setReplacing(); - void revertToProvisional(DocumentLoader*); - void setMainDocumentError(DocumentLoader*, const ResourceError&); - void mainReceivedCompleteError(DocumentLoader*, const ResourceError&); - bool subframeIsLoading() const; - void willChangeTitle(DocumentLoader*); - void didChangeTitle(DocumentLoader*); - - FrameLoadType loadType() const; - CachePolicy subresourceCachePolicy() const; - - void didFirstLayout(); - bool firstLayoutDone() const; - - void didFirstVisuallyNonEmptyLayout(); - - void loadedResourceFromMemoryCache(const CachedResource*); - void tellClientAboutPastMemoryCacheLoads(); - - void checkLoadComplete(); - void detachFromParent(); - void detachViewsAndDocumentLoader(); - - void addExtraFieldsToSubresourceRequest(ResourceRequest&); - void addExtraFieldsToMainResourceRequest(ResourceRequest&); - - static void addHTTPOriginIfNeeded(ResourceRequest&, String origin); + void loadedResourceFromMemoryCache(const CachedResource*); + void tellClientAboutPastMemoryCacheLoads(); - FrameLoaderClient* client() const { return m_client; } + void checkLoadComplete(); + void detachFromParent(); + void detachViewsAndDocumentLoader(); - void setDefersLoading(bool); + void addExtraFieldsToSubresourceRequest(ResourceRequest&); + void addExtraFieldsToMainResourceRequest(ResourceRequest&); + + static void addHTTPOriginIfNeeded(ResourceRequest&, String origin); - void changeLocation(const KURL&, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false, bool refresh = false); - void urlSelected(const ResourceRequest&, const String& target, PassRefPtr<Event>, bool lockHistory, bool lockBackForwardList, bool userGesture); - bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName); + FrameLoaderClient* client() const { return m_client; } - void submitForm(const char* action, const String& url, - PassRefPtr<FormData>, const String& target, const String& contentType, const String& boundary, - bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>); + void setDefersLoading(bool); - void stop(); - void stopLoading(UnloadEventPolicy, DatabasePolicy = DatabasePolicyStop); - bool closeURL(); + void changeLocation(const KURL&, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false, bool refresh = false); + void urlSelected(const ResourceRequest&, const String& target, PassRefPtr<Event>, bool lockHistory, bool lockBackForwardList, bool userGesture, ReferrerPolicy); + bool requestFrame(HTMLFrameOwnerElement*, const String& url, const AtomicString& frameName); - void didExplicitOpen(); + void submitForm(const char* action, const String& url, + PassRefPtr<FormData>, const String& target, const String& contentType, const String& boundary, + bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>); - KURL iconURL(); - void commitIconURLToIconDatabase(const KURL&); + void stop(); + void stopLoading(UnloadEventPolicy, DatabasePolicy = DatabasePolicyStop); + bool closeURL(); - KURL baseURL() const; + void didExplicitOpen(); - void begin(); - void begin(const KURL&, bool dispatchWindowObjectAvailable = true, SecurityOrigin* forcedSecurityOrigin = 0); + KURL iconURL(); + void commitIconURLToIconDatabase(const KURL&); - void write(const char* string, int length = -1, bool flush = false); - void write(const String&); - void end(); - void endIfNotLoadingMainResource(); + KURL baseURL() const; - void setEncoding(const String& encoding, bool userChosen); - String encoding() const; + void replaceDocument(const String&); - ScriptValue executeScript(const ScriptSourceCode&); - ScriptValue executeScript(const String& script, bool forceUserGesture = false); + void begin(); + void begin(const KURL&, bool dispatchWindowObjectAvailable = true, SecurityOrigin* forcedSecurityOrigin = 0); - void gotoAnchor(); + void write(const char* string, int length = -1, bool flush = false); + void write(const String&); + void end(); + void endIfNotLoadingMainResource(); - void tokenizerProcessedData(); + void setEncoding(const String& encoding, bool userChosen); + String encoding() const; - void handledOnloadEvents(); - String userAgent(const KURL&) const; + void tokenizerProcessedData(); - PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const HashMap<String, String>& args); + void handledOnloadEvents(); + String userAgent(const KURL&) const; - void dispatchWindowObjectAvailable(); - void dispatchDocumentElementAvailable(); - void restoreDocumentState(); + PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const HashMap<String, String>& args); - // Mixed content related functions. - static bool isMixedContent(SecurityOrigin* context, const KURL&); - void checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL&); - void checkIfRunInsecureContent(SecurityOrigin* context, const KURL&); + void dispatchWindowObjectAvailable(); + void dispatchDocumentElementAvailable(); - Frame* opener(); - void setOpener(Frame*); + // Mixed content related functions. + static bool isMixedContent(SecurityOrigin* context, const KURL&); + void checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL&); + void checkIfRunInsecureContent(SecurityOrigin* context, const KURL&); - bool isProcessingUserGesture(); + Frame* opener(); + void setOpener(Frame*); - void resetMultipleFormSubmissionProtection(); + bool isProcessingUserGesture(); - void addData(const char* bytes, int length); + void resetMultipleFormSubmissionProtection(); - void checkCallImplicitClose(); + void addData(const char* bytes, int length); - void frameDetached(); + void checkCallImplicitClose(); - const KURL& url() const { return m_URL; } + void frameDetached(); - void setResponseMIMEType(const String&); - const String& responseMIMEType() const; + const KURL& url() const { return m_URL; } - bool containsPlugins() const; + void setResponseMIMEType(const String&); + const String& responseMIMEType() const; - void loadDone(); - void finishedParsing(); - void checkCompleted(); + bool containsPlugins() const; - bool isComplete() const; + void loadDone(); + void finishedParsing(); + void checkCompleted(); - bool requestObject(RenderPart* frame, const String& url, const AtomicString& frameName, - const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues); + void checkDidPerformFirstNavigation(); - KURL completeURL(const String& url); + bool isComplete() const; - void cancelAndClear(); + bool requestObject(RenderPart* frame, const String& url, const AtomicString& frameName, + const String& serviceType, const Vector<String>& paramNames, const Vector<String>& paramValues); - void setTitle(const String&); + KURL completeURL(const String& url); - void commitProvisionalLoad(PassRefPtr<CachedPage>); - bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; } + void cancelAndClear(); - void goToItem(HistoryItem*, FrameLoadType); - void saveDocumentAndScrollState(); + void setTitle(const String&); - HistoryItem* currentHistoryItem(); - void setCurrentHistoryItem(PassRefPtr<HistoryItem>); + void commitProvisionalLoad(PassRefPtr<CachedPage>); + bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; } - bool committingFirstRealLoad() const { return !m_creatingInitialEmptyDocument && !m_committedFirstRealDocumentLoad; } - bool committedFirstRealDocumentLoad() const { return m_committedFirstRealDocumentLoad; } + bool committingFirstRealLoad() const { return !m_creatingInitialEmptyDocument && !m_committedFirstRealDocumentLoad; } + bool committedFirstRealDocumentLoad() const { return m_committedFirstRealDocumentLoad; } + bool creatingInitialEmptyDocument() const { return m_creatingInitialEmptyDocument; } - void iconLoadDecisionAvailable(); + void iconLoadDecisionAvailable(); - bool shouldAllowNavigation(Frame* targetFrame) const; - Frame* findFrameForNavigation(const AtomicString& name); + bool shouldAllowNavigation(Frame* targetFrame) const; + Frame* findFrameForNavigation(const AtomicString& name); - void startIconLoader(); + void startIconLoader(); - void applyUserAgent(ResourceRequest& request); + void applyUserAgent(ResourceRequest& request); - bool shouldInterruptLoadForXFrameOptions(const String&, const KURL&); + bool shouldInterruptLoadForXFrameOptions(const String&, const KURL&); - void open(CachedFrameBase&); + void open(CachedFrameBase&); - // FIXME: Should these really be public? - void completed(); - bool allAncestorsAreComplete() const; // including this - bool allChildrenAreComplete() const; // immediate children, not all descendants - void clientRedirected(const KURL&, double delay, double fireDate, bool lockBackForwardList); - void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress); + // FIXME: Should these really be public? + void completed(); + bool allAncestorsAreComplete() const; // including this + bool allChildrenAreComplete() const; // immediate children, not all descendants + void clientRedirected(const KURL&, double delay, double fireDate, bool lockBackForwardList); + void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress); + void loadItem(HistoryItem*, FrameLoadType); - // FIXME: This is public because this asynchronous callback from the FrameLoaderClient - // uses the policy machinery (and therefore is called via the PolicyChecker). Once we - // introduce a proper callback type for this function, we should make it private again. - void continueLoadAfterWillSubmitForm(); + // FIXME: This is public because this asynchronous callback from the FrameLoaderClient + // uses the policy machinery (and therefore is called via the PolicyChecker). Once we + // introduce a proper callback type for this function, we should make it private again. + void continueLoadAfterWillSubmitForm(); + + bool suppressOpenerInNewFrame() const { return m_suppressOpenerInNewFrame; } - private: - PassRefPtr<HistoryItem> createHistoryItem(bool useOriginal); - PassRefPtr<HistoryItem> createHistoryItemTree(Frame* targetFrame, bool clipAtTarget); + static ObjectContentType defaultObjectContentType(const KURL& url, const String& mimeType); - bool canCachePageContainingThisFrame(); +private: + bool canCachePageContainingThisFrame(); #ifndef NDEBUG - void logCanCachePageDecision(); - bool logCanCacheFrameDecision(int indentLevel); + void logCanCachePageDecision(); + bool logCanCacheFrameDecision(int indentLevel); #endif - void addBackForwardItemClippedAtTarget(bool doClip); - void restoreScrollPositionAndViewState(); - void saveDocumentState(); - void loadItem(HistoryItem*, FrameLoadType); - bool urlsMatchItem(HistoryItem*) const; - void invalidateCurrentItemCachedPage(); - void recursiveGoToItem(HistoryItem*, HistoryItem*, FrameLoadType); - bool childFramesMatchItem(HistoryItem*) const; - - void updateHistoryForBackForwardNavigation(); - void updateHistoryForReload(); - void updateHistoryForStandardLoad(); - void updateHistoryForRedirectWithLockedBackForwardList(); - void updateHistoryForClientRedirect(); - void updateHistoryForCommit(); - void updateHistoryForAnchorScroll(); - - void checkTimerFired(Timer<FrameLoader>*); - - void started(); - - bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); - bool loadPlugin(RenderPart*, const KURL&, const String& mimeType, - const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); - - bool loadProvisionalItemFromCachedPage(); - void cachePageForHistoryItem(HistoryItem*); - void pageHidden(); + void checkTimerFired(Timer<FrameLoader>*); - void receivedFirstData(); + void started(); - void updateFirstPartyForCookies(); - void setFirstPartyForCookies(const KURL&); - - void addExtraFieldsToRequest(ResourceRequest&, FrameLoadType loadType, bool isMainResource, bool cookiePolicyURLFromRequest); + bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback); + bool loadPlugin(RenderPart*, const KURL&, const String& mimeType, + const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback); + + bool loadProvisionalItemFromCachedPage(); + void cachePageForHistoryItem(HistoryItem*); + void pageHidden(); - // Also not cool. - void stopLoadingSubframes(); + void receivedFirstData(); - void clearProvisionalLoad(); - void markLoadComplete(); - void transitionToCommitted(PassRefPtr<CachedPage>); - void frameLoadCompleted(); + void updateFirstPartyForCookies(); + void setFirstPartyForCookies(const KURL&); + + void addExtraFieldsToRequest(ResourceRequest&, FrameLoadType loadType, bool isMainResource, bool cookiePolicyURLFromRequest); - void mainReceivedError(const ResourceError&, bool isComplete); + // Also not cool. + void stopLoadingSubframes(); - void setLoadType(FrameLoadType); + void clearProvisionalLoad(); + void markLoadComplete(); + void transitionToCommitted(PassRefPtr<CachedPage>); + void frameLoadCompleted(); - static void callContinueLoadAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - static void callContinueLoadAfterNewWindowPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); - static void callContinueFragmentScrollAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); + void mainReceivedError(const ResourceError&, bool isComplete); - void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); - void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue); + void setLoadType(FrameLoadType); - bool shouldScrollToAnchor(bool isFormSubmission, FrameLoadType, const KURL&); - void addHistoryItemForFragmentScroll(); + static void callContinueLoadAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); + static void callContinueLoadAfterNewWindowPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); + static void callContinueFragmentScrollAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - void checkLoadCompleteForThisFrame(); + void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); + void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); + void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue); - void setDocumentLoader(DocumentLoader*); - void setPolicyDocumentLoader(DocumentLoader*); - void setProvisionalDocumentLoader(DocumentLoader*); + bool shouldScrollToAnchor(bool isFormSubmission, FrameLoadType, const KURL&); - void setState(FrameState); + void checkLoadCompleteForThisFrame(); - void closeOldDataSources(); - void open(CachedPage&); + void setDocumentLoader(DocumentLoader*); + void setPolicyDocumentLoader(DocumentLoader*); + void setProvisionalDocumentLoader(DocumentLoader*); - void updateHistoryAfterClientRedirect(); + void setState(FrameState); - void clear(bool clearWindowProperties = true, bool clearScriptObjects = true, bool clearFrameView = true); + void closeOldDataSources(); + void open(CachedPage&); - bool shouldReloadToHandleUnreachableURL(DocumentLoader*); + void updateHistoryAfterClientRedirect(); - void dispatchDidCommitLoad(); - void dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); - void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); - void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); - void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int length); - void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier); + void clear(bool clearWindowProperties = true, bool clearScriptObjects = true, bool clearFrameView = true); - void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>); // Calls continueLoadAfterNavigationPolicy - void load(DocumentLoader*); // Calls loadWithDocumentLoader + bool shouldReloadToHandleUnreachableURL(DocumentLoader*); - void loadWithNavigationAction(const ResourceRequest&, const NavigationAction&, // Calls loadWithDocumentLoader - bool lockHistory, FrameLoadType, PassRefPtr<FormState>); + void dispatchDidCommitLoad(); +<<<<<<< HEAD:WebCore/loader/FrameLoader.h #ifdef ANDROID_USER_GESTURE void loadPostRequest(const ResourceRequest&, const String& referrer, // Called by loadFrameRequest, calls loadWithNavigationAction const String& frameName, bool lockHistory, FrameLoadType, PassRefPtr<Event>, PassRefPtr<FormState>, bool); @@ -449,118 +453,121 @@ namespace WebCore { void loadURL(const KURL&, const String& referrer, const String& frameName, // Called by loadFrameRequest, calls loadWithNavigationAction or dispatches to navigation policy delegate bool lockHistory, FrameLoadType, PassRefPtr<Event>, PassRefPtr<FormState>); #endif +======= + void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>); // Calls continueLoadAfterNavigationPolicy + void load(DocumentLoader*); // Calls loadWithDocumentLoader +>>>>>>> webkit.org at r50258.:WebCore/loader/FrameLoader.h - bool shouldReload(const KURL& currentURL, const KURL& destinationURL); + void loadWithNavigationAction(const ResourceRequest&, const NavigationAction&, // Calls loadWithDocumentLoader + bool lockHistory, FrameLoadType, PassRefPtr<FormState>); - void sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse&, int length, const ResourceError&); - void requestFromDelegate(ResourceRequest&, unsigned long& identifier, ResourceError&); + void loadPostRequest(const ResourceRequest&, const String& referrer, // Called by loadFrameRequest, calls loadWithNavigationAction + const String& frameName, bool lockHistory, FrameLoadType, PassRefPtr<Event>, PassRefPtr<FormState>); + void loadURL(const KURL&, const String& referrer, const String& frameName, // Called by loadFrameRequest, calls loadWithNavigationAction or dispatches to navigation policy delegate + bool lockHistory, FrameLoadType, PassRefPtr<Event>, PassRefPtr<FormState>); - void recursiveCheckLoadComplete(); + bool shouldReload(const KURL& currentURL, const KURL& destinationURL); - void detachChildren(); - void closeAndRemoveChild(Frame*); + void requestFromDelegate(ResourceRequest&, unsigned long& identifier, ResourceError&); - Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer); + void recursiveCheckLoadComplete(); - // Returns true if argument is a JavaScript URL. - bool executeIfJavaScriptURL(const KURL&, bool userGesture = false, bool replaceDocument = true); + void detachChildren(); + void closeAndRemoveChild(Frame*); - bool gotoAnchor(const String& name); // returns true if the anchor was found - void scrollToAnchor(const KURL&); + Frame* loadSubframe(HTMLFrameOwnerElement*, const KURL&, const String& name, const String& referrer); - void provisionalLoadStarted(); + void scrollToAnchor(const KURL&); - bool canCachePage(); + void provisionalLoadStarted(); - bool didOpenURL(const KURL&); + bool canCachePage(); - void scheduleCheckCompleted(); - void scheduleCheckLoadComplete(); - void startCheckCompleteTimer(); + bool didOpenURL(const KURL&); - KURL originalRequestURL() const; + void scheduleCheckCompleted(); + void scheduleCheckLoadComplete(); + void startCheckCompleteTimer(); - bool shouldTreatURLAsSameAsCurrent(const KURL&) const; + KURL originalRequestURL() const; - void saveScrollPositionAndViewStateToItem(HistoryItem*); + bool shouldTreatURLAsSameAsCurrent(const KURL&) const; - Frame* m_frame; - FrameLoaderClient* m_client; + Frame* m_frame; + FrameLoaderClient* m_client; - PolicyChecker m_policyChecker; + mutable PolicyChecker m_policyChecker; + mutable HistoryController m_history; + mutable ResourceLoadNotifier m_notifer; - FrameState m_state; - FrameLoadType m_loadType; + FrameState m_state; + FrameLoadType m_loadType; - // Document loaders for the three phases of frame loading. Note that while - // a new request is being loaded, the old document loader may still be referenced. - // E.g. while a new request is in the "policy" state, the old document loader may - // be consulted in particular as it makes sense to imply certain settings on the new loader. - RefPtr<DocumentLoader> m_documentLoader; - RefPtr<DocumentLoader> m_provisionalDocumentLoader; - RefPtr<DocumentLoader> m_policyDocumentLoader; + // Document loaders for the three phases of frame loading. Note that while + // a new request is being loaded, the old document loader may still be referenced. + // E.g. while a new request is in the "policy" state, the old document loader may + // be consulted in particular as it makes sense to imply certain settings on the new loader. + RefPtr<DocumentLoader> m_documentLoader; + RefPtr<DocumentLoader> m_provisionalDocumentLoader; + RefPtr<DocumentLoader> m_policyDocumentLoader; - bool m_delegateIsHandlingProvisionalLoadError; + bool m_delegateIsHandlingProvisionalLoadError; - bool m_firstLayoutDone; - bool m_quickRedirectComing; - bool m_sentRedirectNotification; - bool m_inStopAllLoaders; + bool m_firstLayoutDone; + bool m_quickRedirectComing; + bool m_sentRedirectNotification; + bool m_inStopAllLoaders; - String m_outgoingReferrer; + String m_outgoingReferrer; - bool m_isExecutingJavaScriptFormAction; - bool m_isRunningScript; + bool m_isExecutingJavaScriptFormAction; - String m_responseMIMEType; + String m_responseMIMEType; - bool m_didCallImplicitClose; - bool m_wasUnloadEventEmitted; - bool m_unloadEventBeingDispatched; - bool m_isComplete; - bool m_isLoadingMainResource; + bool m_didCallImplicitClose; + bool m_wasUnloadEventEmitted; + bool m_unloadEventBeingDispatched; + bool m_isComplete; + bool m_isLoadingMainResource; - KURL m_URL; - KURL m_workingURL; + KURL m_URL; + KURL m_workingURL; - OwnPtr<IconLoader> m_iconLoader; - bool m_mayLoadIconLater; + OwnPtr<IconLoader> m_iconLoader; + bool m_mayLoadIconLater; - bool m_cancellingWithLoadInProgress; + bool m_cancellingWithLoadInProgress; - bool m_needsClear; - bool m_receivedData; + bool m_needsClear; + bool m_receivedData; - bool m_encodingWasChosenByUser; - String m_encoding; - RefPtr<TextResourceDecoder> m_decoder; + bool m_encodingWasChosenByUser; + String m_encoding; + RefPtr<TextResourceDecoder> m_decoder; - bool m_containsPlugIns; + bool m_containsPlugIns; - KURL m_submittedFormURL; + KURL m_submittedFormURL; - Timer<FrameLoader> m_checkTimer; - bool m_shouldCallCheckCompleted; - bool m_shouldCallCheckLoadComplete; + Timer<FrameLoader> m_checkTimer; + bool m_shouldCallCheckCompleted; + bool m_shouldCallCheckLoadComplete; - Frame* m_opener; - HashSet<Frame*> m_openedFrames; + Frame* m_opener; + HashSet<Frame*> m_openedFrames; - bool m_creatingInitialEmptyDocument; - bool m_isDisplayingInitialEmptyDocument; - bool m_committedFirstRealDocumentLoad; + bool m_creatingInitialEmptyDocument; + bool m_isDisplayingInitialEmptyDocument; + bool m_committedFirstRealDocumentLoad; - RefPtr<HistoryItem> m_currentHistoryItem; - RefPtr<HistoryItem> m_previousHistoryItem; - RefPtr<HistoryItem> m_provisionalHistoryItem; - - bool m_didPerformFirstNavigation; - bool m_loadingFromCachedPage; - + bool m_didPerformFirstNavigation; + bool m_loadingFromCachedPage; + bool m_suppressOpenerInNewFrame; + #ifndef NDEBUG - bool m_didDispatchDidCommitLoad; + bool m_didDispatchDidCommitLoad; #endif - }; +}; } // namespace WebCore diff --git a/WebCore/loader/FrameLoaderTypes.h b/WebCore/loader/FrameLoaderTypes.h index 76299f5..e7d51c7 100644 --- a/WebCore/loader/FrameLoaderTypes.h +++ b/WebCore/loader/FrameLoaderTypes.h @@ -87,6 +87,11 @@ namespace WebCore { UnloadEventPolicyUnloadOnly, UnloadEventPolicyUnloadAndPageHide }; + + enum ReferrerPolicy { + SendReferrer, + NoReferrer + }; } #endif diff --git a/WebCore/loader/HistoryController.cpp b/WebCore/loader/HistoryController.cpp new file mode 100644 index 0000000..501640a --- /dev/null +++ b/WebCore/loader/HistoryController.cpp @@ -0,0 +1,627 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "HistoryController.h" + +#include "CachedPage.h" +#include "CString.h" +#include "DocumentLoader.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameLoaderClient.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "HistoryItem.h" +#include "Logging.h" +#include "Page.h" +#include "PageCache.h" +#include "PageGroup.h" +#include "Settings.h" + +namespace WebCore { + +HistoryController::HistoryController(Frame* frame) + : m_frame(frame) +{ +} + +HistoryController::~HistoryController() +{ +} + +void HistoryController::saveScrollPositionAndViewStateToItem(HistoryItem* item) +{ + if (!item || !m_frame->view()) + return; + + item->setScrollPoint(m_frame->view()->scrollPosition()); + // FIXME: It would be great to work out a way to put this code in WebCore instead of calling through to the client. + m_frame->loader()->client()->saveViewStateToItem(item); +} + +/* + There is a race condition between the layout and load completion that affects restoring the scroll position. + We try to restore the scroll position at both the first layout and upon load completion. + + 1) If first layout happens before the load completes, we want to restore the scroll position then so that the + first time we draw the page is already scrolled to the right place, instead of starting at the top and later + jumping down. It is possible that the old scroll position is past the part of the doc laid out so far, in + which case the restore silent fails and we will fix it in when we try to restore on doc completion. + 2) If the layout happens after the load completes, the attempt to restore at load completion time silently + fails. We then successfully restore it when the layout happens. +*/ +void HistoryController::restoreScrollPositionAndViewState() +{ + if (!m_frame->loader()->committedFirstRealDocumentLoad()) + return; + + ASSERT(m_currentItem); + + // FIXME: As the ASSERT attests, it seems we should always have a currentItem here. + // One counterexample is <rdar://problem/4917290> + // For now, to cover this issue in release builds, there is no technical harm to returning + // early and from a user standpoint - as in the above radar - the previous page load failed + // so there *is* no scroll or view state to restore! + if (!m_currentItem) + return; + + // FIXME: It would be great to work out a way to put this code in WebCore instead of calling + // through to the client. It's currently used only for the PDF view on Mac. + m_frame->loader()->client()->restoreViewState(); + + if (FrameView* view = m_frame->view()) + if (!view->wasScrolledByUser()) + view->setScrollPosition(m_currentItem->scrollPoint()); +} + +void HistoryController::updateBackForwardListForFragmentScroll() +{ + updateBackForwardListClippedAtTarget(false); +} + +void HistoryController::saveDocumentState() +{ + // FIXME: Reading this bit of FrameLoader state here is unfortunate. I need to study + // this more to see if we can remove this dependency. + if (m_frame->loader()->creatingInitialEmptyDocument()) + return; + + // For a standard page load, we will have a previous item set, which will be used to + // store the form state. However, in some cases we will have no previous item, and + // the current item is the right place to save the state. One example is when we + // detach a bunch of frames because we are navigating from a site with frames to + // another site. Another is when saving the frame state of a frame that is not the + // target of the current navigation (if we even decide to save with that granularity). + + // Because of previousItem's "masking" of currentItem for this purpose, it's important + // that previousItem be cleared at the end of a page transition. We leverage the + // checkLoadComplete recursion to achieve this goal. + + HistoryItem* item = m_previousItem ? m_previousItem.get() : m_currentItem.get(); + if (!item) + return; + + Document* document = m_frame->document(); + ASSERT(document); + + if (item->isCurrentDocument(document)) { + LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().string().utf8().data(), item); + item->setDocumentState(document->formElementsState()); + } +} + +// Walk the frame tree, telling all frames to save their form state into their current +// history item. +void HistoryController::saveDocumentAndScrollState() +{ + for (Frame* frame = m_frame; frame; frame = frame->tree()->traverseNext(m_frame)) { + frame->loader()->history()->saveDocumentState(); + frame->loader()->history()->saveScrollPositionAndViewStateToItem(frame->loader()->history()->currentItem()); + } +} + +void HistoryController::restoreDocumentState() +{ + Document* doc = m_frame->document(); + + HistoryItem* itemToRestore = 0; + + switch (m_frame->loader()->loadType()) { + case FrameLoadTypeReload: + case FrameLoadTypeReloadFromOrigin: + case FrameLoadTypeSame: + case FrameLoadTypeReplace: + break; + case FrameLoadTypeBack: + case FrameLoadTypeBackWMLDeckNotAccessible: + case FrameLoadTypeForward: + case FrameLoadTypeIndexedBackForward: + case FrameLoadTypeRedirectWithLockedBackForwardList: + case FrameLoadTypeStandard: + itemToRestore = m_currentItem.get(); + } + + if (!itemToRestore) + return; + + LOG(Loading, "WebCoreLoading %s: restoring form state from %p", m_frame->tree()->name().string().utf8().data(), itemToRestore); + doc->setStateForNewFormElements(itemToRestore->documentState()); +} + +void HistoryController::invalidateCurrentItemCachedPage() +{ + // When we are pre-commit, the currentItem is where the pageCache data resides + CachedPage* cachedPage = pageCache()->get(currentItem()); + + // FIXME: This is a grotesque hack to fix <rdar://problem/4059059> Crash in RenderFlow::detach + // Somehow the PageState object is not properly updated, and is holding onto a stale document. + // Both Xcode and FileMaker see this crash, Safari does not. + + ASSERT(!cachedPage || cachedPage->document() == m_frame->document()); + if (cachedPage && cachedPage->document() == m_frame->document()) { + cachedPage->document()->setInPageCache(false); + cachedPage->clear(); + } + + if (cachedPage) + pageCache()->remove(currentItem()); +} + +// Main funnel for navigating to a previous location (back/forward, non-search snap-back) +// This includes recursion to handle loading into framesets properly +void HistoryController::goToItem(HistoryItem* targetItem, FrameLoadType type) +{ + ASSERT(!m_frame->tree()->parent()); + + // shouldGoToHistoryItem is a private delegate method. This is needed to fix: + // <rdar://problem/3951283> can view pages from the back/forward cache that should be disallowed by Parental Controls + // Ultimately, history item navigations should go through the policy delegate. That's covered in: + // <rdar://problem/3979539> back/forward cache navigations should consult policy delegate + Page* page = m_frame->page(); + if (!page) + return; + if (!m_frame->loader()->client()->shouldGoToHistoryItem(targetItem)) + return; + + // Set the BF cursor before commit, which lets the user quickly click back/forward again. + // - plus, it only makes sense for the top level of the operation through the frametree, + // as opposed to happening for some/one of the page commits that might happen soon + BackForwardList* bfList = page->backForwardList(); + HistoryItem* currentItem = bfList->currentItem(); + bfList->goToItem(targetItem); + Settings* settings = m_frame->settings(); + page->setGlobalHistoryItem((!settings || settings->privateBrowsingEnabled()) ? 0 : targetItem); + recursiveGoToItem(targetItem, currentItem, type); +} + +// Walk the frame tree and ensure that the URLs match the URLs in the item. +bool HistoryController::urlsMatchItem(HistoryItem* item) const +{ + const KURL& currentURL = m_frame->loader()->documentLoader()->url(); + if (!equalIgnoringFragmentIdentifier(currentURL, item->url())) + return false; + + const HistoryItemVector& childItems = item->children(); + + unsigned size = childItems.size(); + for (unsigned i = 0; i < size; ++i) { + Frame* childFrame = m_frame->tree()->child(childItems[i]->target()); + if (childFrame && !childFrame->loader()->history()->urlsMatchItem(childItems[i].get())) + return false; + } + + return true; +} + +void HistoryController::updateForBackForwardNavigation() +{ +#if !LOG_DISABLED + if (m_frame->loader()->documentLoader()) + LOG(History, "WebCoreHistory: Updating History for back/forward navigation in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); +#endif + + // Must grab the current scroll position before disturbing it + saveScrollPositionAndViewStateToItem(m_previousItem.get()); +} + +void HistoryController::updateForReload() +{ +#if !LOG_DISABLED + if (m_frame->loader()->documentLoader()) + LOG(History, "WebCoreHistory: Updating History for reload in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); +#endif + + if (m_currentItem) { + pageCache()->remove(m_currentItem.get()); + + if (m_frame->loader()->loadType() == FrameLoadTypeReload || m_frame->loader()->loadType() == FrameLoadTypeReloadFromOrigin) + saveScrollPositionAndViewStateToItem(m_currentItem.get()); + + // Sometimes loading a page again leads to a different result because of cookies. Bugzilla 4072 + if (m_frame->loader()->documentLoader()->unreachableURL().isEmpty()) + m_currentItem->setURL(m_frame->loader()->documentLoader()->requestURL()); + } +} + +// There are 3 things you might think of as "history", all of which are handled by these functions. +// +// 1) Back/forward: The m_currentItem is part of this mechanism. +// 2) Global history: Handled by the client. +// 3) Visited links: Handled by the PageGroup. + +void HistoryController::updateForStandardLoad() +{ + LOG(History, "WebCoreHistory: Updating History for Standard Load in frame %s", m_frame->loader()->documentLoader()->url().string().ascii().data()); + + FrameLoader* frameLoader = m_frame->loader(); + + Settings* settings = m_frame->settings(); + bool needPrivacy = !settings || settings->privateBrowsingEnabled(); + const KURL& historyURL = frameLoader->documentLoader()->urlForHistory(); + + if (!frameLoader->documentLoader()->isClientRedirect()) { + if (!historyURL.isEmpty()) { + updateBackForwardListClippedAtTarget(true); + if (!needPrivacy) { + frameLoader->client()->updateGlobalHistory(); + frameLoader->documentLoader()->setDidCreateGlobalHistoryEntry(true); + if (frameLoader->documentLoader()->unreachableURL().isEmpty()) + frameLoader->client()->updateGlobalHistoryRedirectLinks(); + } + if (Page* page = m_frame->page()) + page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForwardList()->currentItem()); + } + } else if (frameLoader->documentLoader()->unreachableURL().isEmpty() && m_currentItem) { + m_currentItem->setURL(frameLoader->documentLoader()->url()); + m_currentItem->setFormInfoFromRequest(frameLoader->documentLoader()->request()); + } + + if (!historyURL.isEmpty() && !needPrivacy) { + if (Page* page = m_frame->page()) + page->group().addVisitedLink(historyURL); + + if (!frameLoader->documentLoader()->didCreateGlobalHistoryEntry() && frameLoader->documentLoader()->unreachableURL().isEmpty() && !frameLoader->url().isEmpty()) + frameLoader->client()->updateGlobalHistoryRedirectLinks(); + } +} + +void HistoryController::updateForRedirectWithLockedBackForwardList() +{ +#if !LOG_DISABLED + if (m_frame->loader()->documentLoader()) + LOG(History, "WebCoreHistory: Updating History for redirect load in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); +#endif + + Settings* settings = m_frame->settings(); + bool needPrivacy = !settings || settings->privateBrowsingEnabled(); + const KURL& historyURL = m_frame->loader()->documentLoader()->urlForHistory(); + + if (m_frame->loader()->documentLoader()->isClientRedirect()) { + if (!m_currentItem && !m_frame->tree()->parent()) { + if (!historyURL.isEmpty()) { + updateBackForwardListClippedAtTarget(true); + if (!needPrivacy) { + m_frame->loader()->client()->updateGlobalHistory(); + m_frame->loader()->documentLoader()->setDidCreateGlobalHistoryEntry(true); + if (m_frame->loader()->documentLoader()->unreachableURL().isEmpty()) + m_frame->loader()->client()->updateGlobalHistoryRedirectLinks(); + } + if (Page* page = m_frame->page()) + page->setGlobalHistoryItem(needPrivacy ? 0 : page->backForwardList()->currentItem()); + } + } + if (m_currentItem) { + m_currentItem->setURL(m_frame->loader()->documentLoader()->url()); + m_currentItem->setFormInfoFromRequest(m_frame->loader()->documentLoader()->request()); + } + } else { + Frame* parentFrame = m_frame->tree()->parent(); + if (parentFrame && parentFrame->loader()->history()->m_currentItem) + parentFrame->loader()->history()->m_currentItem->setChildItem(createItem(true)); + } + + if (!historyURL.isEmpty() && !needPrivacy) { + if (Page* page = m_frame->page()) + page->group().addVisitedLink(historyURL); + + if (!m_frame->loader()->documentLoader()->didCreateGlobalHistoryEntry() && m_frame->loader()->documentLoader()->unreachableURL().isEmpty() && !m_frame->loader()->url().isEmpty()) + m_frame->loader()->client()->updateGlobalHistoryRedirectLinks(); + } +} + +void HistoryController::updateForClientRedirect() +{ +#if !LOG_DISABLED + if (m_frame->loader()->documentLoader()) + LOG(History, "WebCoreHistory: Updating History for client redirect in frame %s", m_frame->loader()->documentLoader()->title().utf8().data()); +#endif + + // Clear out form data so we don't try to restore it into the incoming page. Must happen after + // webcore has closed the URL and saved away the form state. + if (m_currentItem) { + m_currentItem->clearDocumentState(); + m_currentItem->clearScrollPoint(); + } + + Settings* settings = m_frame->settings(); + bool needPrivacy = !settings || settings->privateBrowsingEnabled(); + const KURL& historyURL = m_frame->loader()->documentLoader()->urlForHistory(); + + if (!historyURL.isEmpty() && !needPrivacy) { + if (Page* page = m_frame->page()) + page->group().addVisitedLink(historyURL); + } +} + +void HistoryController::updateForCommit() +{ + FrameLoader* frameLoader = m_frame->loader(); +#if !LOG_DISABLED + if (frameLoader->documentLoader()) + LOG(History, "WebCoreHistory: Updating History for commit in frame %s", frameLoader->documentLoader()->title().utf8().data()); +#endif + FrameLoadType type = frameLoader->loadType(); + if (isBackForwardLoadType(type) || + ((type == FrameLoadTypeReload || type == FrameLoadTypeReloadFromOrigin) && !frameLoader->provisionalDocumentLoader()->unreachableURL().isEmpty())) { + // Once committed, we want to use current item for saving DocState, and + // the provisional item for restoring state. + // Note previousItem must be set before we close the URL, which will + // happen when the data source is made non-provisional below + m_previousItem = m_currentItem; + ASSERT(m_provisionalItem); + m_currentItem = m_provisionalItem; + m_provisionalItem = 0; + } +} + +void HistoryController::updateForAnchorScroll() +{ + if (m_frame->loader()->url().isEmpty()) + return; + + Settings* settings = m_frame->settings(); + if (!settings || settings->privateBrowsingEnabled()) + return; + + Page* page = m_frame->page(); + if (!page) + return; + + page->group().addVisitedLink(m_frame->loader()->url()); +} + +void HistoryController::updateForFrameLoadCompleted() +{ + // Even if already complete, we might have set a previous item on a frame that + // didn't do any data loading on the past transaction. Make sure to clear these out. + m_previousItem = 0; +} + +void HistoryController::setCurrentItem(HistoryItem* item) +{ + m_currentItem = item; +} + +void HistoryController::setCurrentItemTitle(const String& title) +{ + if (m_currentItem) + m_currentItem->setTitle(title); +} + +void HistoryController::setProvisionalItem(HistoryItem* item) +{ + m_provisionalItem = item; +} + +PassRefPtr<HistoryItem> HistoryController::createItem(bool useOriginal) +{ + DocumentLoader* docLoader = m_frame->loader()->documentLoader(); + + KURL unreachableURL = docLoader ? docLoader->unreachableURL() : KURL(); + + KURL url; + KURL originalURL; + + if (!unreachableURL.isEmpty()) { + url = unreachableURL; + originalURL = unreachableURL; + } else { + originalURL = docLoader ? docLoader->originalURL() : KURL(); + if (useOriginal) + url = originalURL; + else if (docLoader) + url = docLoader->requestURL(); + } + + LOG(History, "WebCoreHistory: Creating item for %s", url.string().ascii().data()); + + // Frames that have never successfully loaded any content + // may have no URL at all. Currently our history code can't + // deal with such things, so we nip that in the bud here. + // Later we may want to learn to live with nil for URL. + // See bug 3368236 and related bugs for more information. + if (url.isEmpty()) + url = blankURL(); + if (originalURL.isEmpty()) + originalURL = blankURL(); + + Frame* parentFrame = m_frame->tree()->parent(); + String parent = parentFrame ? parentFrame->tree()->name() : ""; + String title = docLoader ? docLoader->title() : ""; + + RefPtr<HistoryItem> item = HistoryItem::create(url, m_frame->tree()->name(), parent, title); + item->setOriginalURLString(originalURL.string()); + + if (!unreachableURL.isEmpty() || !docLoader || docLoader->response().httpStatusCode() >= 400) + item->setLastVisitWasFailure(true); + + // Save form state if this is a POST + if (docLoader) { + if (useOriginal) + item->setFormInfoFromRequest(docLoader->originalRequest()); + else + item->setFormInfoFromRequest(docLoader->request()); + } + + // Set the item for which we will save document state + m_previousItem = m_currentItem; + m_currentItem = item; + + return item.release(); +} + +PassRefPtr<HistoryItem> HistoryController::createItemTree(Frame* targetFrame, bool clipAtTarget) +{ + RefPtr<HistoryItem> bfItem = createItem(m_frame->tree()->parent() ? true : false); + if (m_previousItem) + saveScrollPositionAndViewStateToItem(m_previousItem.get()); + if (!(clipAtTarget && m_frame == targetFrame)) { + // save frame state for items that aren't loading (khtml doesn't save those) + saveDocumentState(); + for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) { + FrameLoader* childLoader = child->loader(); + bool hasChildLoaded = childLoader->frameHasLoaded(); + + // If the child is a frame corresponding to an <object> element that never loaded, + // we don't want to create a history item, because that causes fallback content + // to be ignored on reload. + + if (!(!hasChildLoaded && childLoader->isHostedByObjectElement())) + bfItem->addChildItem(childLoader->history()->createItemTree(targetFrame, clipAtTarget)); + } + } + if (m_frame == targetFrame) + bfItem->setIsTargetItem(true); + return bfItem; +} + +// The general idea here is to traverse the frame tree and the item tree in parallel, +// tracking whether each frame already has the content the item requests. If there is +// a match (by URL), we just restore scroll position and recurse. Otherwise we must +// reload that frame, and all its kids. +void HistoryController::recursiveGoToItem(HistoryItem* item, HistoryItem* fromItem, FrameLoadType type) +{ + ASSERT(item); + ASSERT(fromItem); + + KURL itemURL = item->url(); + KURL currentURL; + if (m_frame->loader()->documentLoader()) + currentURL = m_frame->loader()->documentLoader()->url(); + + // Always reload the target frame of the item we're going to. This ensures that we will + // do -some- load for the transition, which means a proper notification will be posted + // to the app. + // The exact URL has to match, including fragment. We want to go through the _load + // method, even if to do a within-page navigation. + // The current frame tree and the frame tree snapshot in the item have to match. + if (!item->isTargetItem() && + itemURL == currentURL && + ((m_frame->tree()->name().isEmpty() && item->target().isEmpty()) || m_frame->tree()->name() == item->target()) && + childFramesMatchItem(item)) + { + // This content is good, so leave it alone and look for children that need reloading + // Save form state (works from currentItem, since prevItem is nil) + ASSERT(!m_previousItem); + saveDocumentState(); + saveScrollPositionAndViewStateToItem(m_currentItem.get()); + + if (FrameView* view = m_frame->view()) + view->setWasScrolledByUser(false); + + m_currentItem = item; + + // Restore form state (works from currentItem) + restoreDocumentState(); + + // Restore the scroll position (we choose to do this rather than going back to the anchor point) + restoreScrollPositionAndViewState(); + + const HistoryItemVector& childItems = item->children(); + + int size = childItems.size(); + for (int i = 0; i < size; ++i) { + String childFrameName = childItems[i]->target(); + HistoryItem* fromChildItem = fromItem->childItemWithTarget(childFrameName); + ASSERT(fromChildItem || fromItem->isTargetItem()); + Frame* childFrame = m_frame->tree()->child(childFrameName); + ASSERT(childFrame); + childFrame->loader()->history()->recursiveGoToItem(childItems[i].get(), fromChildItem, type); + } + } else { + m_frame->loader()->loadItem(item, type); + } +} + +// helper method that determines whether the subframes described by the item's subitems +// match our own current frameset +bool HistoryController::childFramesMatchItem(HistoryItem* item) const +{ + const HistoryItemVector& childItems = item->children(); + if (childItems.size() != m_frame->tree()->childCount()) + return false; + + unsigned size = childItems.size(); + for (unsigned i = 0; i < size; ++i) { + if (!m_frame->tree()->child(childItems[i]->target())) + return false; + } + + // Found matches for all item targets + return true; +} + +void HistoryController::updateBackForwardListClippedAtTarget(bool doClip) +{ + // In the case of saving state about a page with frames, we store a tree of items that mirrors the frame tree. + // The item that was the target of the user's navigation is designated as the "targetItem". + // When this function is called with doClip=true we're able to create the whole tree except for the target's children, + // which will be loaded in the future. That part of the tree will be filled out as the child loads are committed. + + Page* page = m_frame->page(); + if (!page) + return; + + if (m_frame->loader()->documentLoader()->urlForHistory().isEmpty()) + return; + + Frame* mainFrame = page->mainFrame(); + ASSERT(mainFrame); + FrameLoader* frameLoader = mainFrame->loader(); + + frameLoader->checkDidPerformFirstNavigation(); + + RefPtr<HistoryItem> item = frameLoader->history()->createItemTree(m_frame, doClip); + LOG(BackForward, "WebCoreBackForward - Adding backforward item %p for frame %s", item.get(), m_frame->loader()->documentLoader()->url().string().ascii().data()); + page->backForwardList()->addItem(item); +} + +} // namespace WebCore diff --git a/WebCore/loader/HistoryController.h b/WebCore/loader/HistoryController.h new file mode 100644 index 0000000..4ecae69 --- /dev/null +++ b/WebCore/loader/HistoryController.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef HistoryController_h +#define HistoryController_h + +#include "FrameLoaderTypes.h" +#include "PlatformString.h" +#include <wtf/Noncopyable.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class Frame; +class HistoryItem; + +class HistoryController : public Noncopyable { +public: + HistoryController(Frame*); + ~HistoryController(); + + void saveScrollPositionAndViewStateToItem(HistoryItem*); + void restoreScrollPositionAndViewState(); + + void updateBackForwardListForFragmentScroll(); + + void saveDocumentState(); + void saveDocumentAndScrollState(); + void restoreDocumentState(); + + void invalidateCurrentItemCachedPage(); + + void goToItem(HistoryItem*, FrameLoadType); + bool urlsMatchItem(HistoryItem*) const; + + void updateForBackForwardNavigation(); + void updateForReload(); + void updateForStandardLoad(); + void updateForRedirectWithLockedBackForwardList(); + void updateForClientRedirect(); + void updateForCommit(); + void updateForAnchorScroll(); + void updateForFrameLoadCompleted(); + + HistoryItem* currentItem() const { return m_currentItem.get(); } + void setCurrentItem(HistoryItem*); + void setCurrentItemTitle(const String&); + + HistoryItem* provisionalItem() const { return m_provisionalItem.get(); } + void setProvisionalItem(HistoryItem*); + +private: + PassRefPtr<HistoryItem> createItem(bool useOriginal); + PassRefPtr<HistoryItem> createItemTree(Frame* targetFrame, bool clipAtTarget); + + void recursiveGoToItem(HistoryItem*, HistoryItem*, FrameLoadType); + bool childFramesMatchItem(HistoryItem*) const; + void updateBackForwardListClippedAtTarget(bool doClip); + + Frame* m_frame; + + RefPtr<HistoryItem> m_currentItem; + RefPtr<HistoryItem> m_previousItem; + RefPtr<HistoryItem> m_provisionalItem; +}; + +} // namespace WebCore + +#endif // HistoryController_h diff --git a/WebCore/loader/ImageLoader.cpp b/WebCore/loader/ImageLoader.cpp index b183a66..cdc31bc 100644 --- a/WebCore/loader/ImageLoader.cpp +++ b/WebCore/loader/ImageLoader.cpp @@ -31,34 +31,40 @@ namespace WebCore { -class ImageLoadEventSender { +class ImageEventSender { public: - ImageLoadEventSender(); + ImageEventSender(const AtomicString& eventType); - void dispatchLoadEventSoon(ImageLoader*); - void cancelLoadEvent(ImageLoader*); + void dispatchEventSoon(ImageLoader*); + void cancelEvent(ImageLoader*); - void dispatchPendingLoadEvents(); + void dispatchPendingEvents(); private: - ~ImageLoadEventSender(); + void timerFired(Timer<ImageEventSender>*); - void timerFired(Timer<ImageLoadEventSender>*); - - Timer<ImageLoadEventSender> m_timer; + AtomicString m_eventType; + Timer<ImageEventSender> m_timer; Vector<ImageLoader*> m_dispatchSoonList; Vector<ImageLoader*> m_dispatchingList; }; -static ImageLoadEventSender& loadEventSender() +static ImageEventSender& beforeLoadEventSender() +{ + DEFINE_STATIC_LOCAL(ImageEventSender, sender, (eventNames().beforeloadEvent)); + return sender; +} + +static ImageEventSender& loadEventSender() { - DEFINE_STATIC_LOCAL(ImageLoadEventSender, sender, ()); + DEFINE_STATIC_LOCAL(ImageEventSender, sender, (eventNames().loadEvent)); return sender; } ImageLoader::ImageLoader(Element* element) : m_element(element) , m_image(0) + , m_firedBeforeLoad(true) , m_firedLoad(true) , m_imageComplete(true) , m_loadManually(false) @@ -69,7 +75,10 @@ ImageLoader::~ImageLoader() { if (m_image) m_image->removeClient(this); - loadEventSender().cancelLoadEvent(this); + if (!m_firedBeforeLoad) + beforeLoadEventSender().cancelEvent(this); + if (!m_firedLoad) + loadEventSender().cancelEvent(this); } void ImageLoader::setImage(CachedImage* newImage) @@ -78,6 +87,7 @@ void ImageLoader::setImage(CachedImage* newImage) CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { setLoadingImage(newImage); + m_firedBeforeLoad = true; m_firedLoad = true; m_imageComplete = true; if (newImage) @@ -89,16 +99,16 @@ void ImageLoader::setImage(CachedImage* newImage) if (RenderObject* renderer = m_element->renderer()) { if (!renderer->isImage()) return; - toRenderImage(renderer)->resetAnimation(); } } void ImageLoader::setLoadingImage(CachedImage* loadingImage) { - m_firedLoad = false; - m_imageComplete = false; m_image = loadingImage; + m_firedBeforeLoad = !loadingImage; + m_firedLoad = !loadingImage; + m_imageComplete = !loadingImage; } void ImageLoader::updateFromElement() @@ -137,8 +147,13 @@ void ImageLoader::updateFromElement() CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { setLoadingImage(newImage); - if (newImage) + if (newImage) { newImage->addClient(this); + if (!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER)) + dispatchPendingBeforeLoadEvent(); + else + beforeLoadEventSender().dispatchEventSoon(this); + } if (oldImage) oldImage->removeClient(this); } @@ -146,7 +161,6 @@ void ImageLoader::updateFromElement() if (RenderObject* renderer = m_element->renderer()) { if (!renderer->isImage()) return; - toRenderImage(renderer)->resetAnimation(); } } @@ -161,16 +175,48 @@ void ImageLoader::updateFromElementIgnoringPreviousError() void ImageLoader::notifyFinished(CachedResource*) { ASSERT(m_failedLoadURL.isEmpty()); + m_imageComplete = true; + if (haveFiredBeforeLoadEvent()) + updateRenderer(); - loadEventSender().dispatchLoadEventSoon(this); + loadEventSender().dispatchEventSoon(this); +} +void ImageLoader::updateRenderer() +{ if (RenderObject* renderer = m_element->renderer()) { if (!renderer->isImage()) return; + RenderImage* imageRenderer = toRenderImage(renderer); + + // Only update the renderer if it doesn't have an image or if what we have + // is a complete image. This prevents flickering in the case where a dynamic + // change is happening between two images. + CachedImage* cachedImage = imageRenderer->cachedImage(); + if (m_image != cachedImage && (m_imageComplete || !imageRenderer->cachedImage())) + imageRenderer->setCachedImage(m_image.get()); + } +} - toRenderImage(renderer)->setCachedImage(m_image.get()); +void ImageLoader::dispatchPendingBeforeLoadEvent() +{ + if (m_firedBeforeLoad) + return; + if (!m_image) + return; + if (!m_element->document()->attached()) + return; + m_firedBeforeLoad = true; + if (m_element->dispatchBeforeLoadEvent(m_image->url())) { + updateRenderer(); + return; + } + if (m_image) { + m_image->removeClient(this); + m_image = 0; } + loadEventSender().cancelEvent(this); } void ImageLoader::dispatchPendingLoadEvent() @@ -185,24 +231,26 @@ void ImageLoader::dispatchPendingLoadEvent() dispatchLoadEvent(); } -void ImageLoader::dispatchPendingLoadEvents() +void ImageLoader::dispatchPendingEvents() { - loadEventSender().dispatchPendingLoadEvents(); + beforeLoadEventSender().dispatchPendingEvents(); + loadEventSender().dispatchPendingEvents(); } -ImageLoadEventSender::ImageLoadEventSender() - : m_timer(this, &ImageLoadEventSender::timerFired) +ImageEventSender::ImageEventSender(const AtomicString& eventType) + : m_eventType(eventType) + , m_timer(this, &ImageEventSender::timerFired) { } -void ImageLoadEventSender::dispatchLoadEventSoon(ImageLoader* loader) +void ImageEventSender::dispatchEventSoon(ImageLoader* loader) { m_dispatchSoonList.append(loader); if (!m_timer.isActive()) m_timer.startOneShot(0); } -void ImageLoadEventSender::cancelLoadEvent(ImageLoader* loader) +void ImageEventSender::cancelEvent(ImageLoader* loader) { // Remove instances of this loader from both lists. // Use loops because we allow multiple instances to get into the lists. @@ -220,7 +268,7 @@ void ImageLoadEventSender::cancelLoadEvent(ImageLoader* loader) m_timer.stop(); } -void ImageLoadEventSender::dispatchPendingLoadEvents() +void ImageEventSender::dispatchPendingEvents() { // Need to avoid re-entering this function; if new dispatches are // scheduled before the parent finishes processing the list, they @@ -233,15 +281,19 @@ void ImageLoadEventSender::dispatchPendingLoadEvents() m_dispatchingList.swap(m_dispatchSoonList); size_t size = m_dispatchingList.size(); for (size_t i = 0; i < size; ++i) { - if (ImageLoader* loader = m_dispatchingList[i]) - loader->dispatchPendingLoadEvent(); + if (ImageLoader* loader = m_dispatchingList[i]) { + if (m_eventType == eventNames().beforeloadEvent) + loader->dispatchPendingBeforeLoadEvent(); + else + loader->dispatchPendingLoadEvent(); + } } m_dispatchingList.clear(); } -void ImageLoadEventSender::timerFired(Timer<ImageLoadEventSender>*) +void ImageEventSender::timerFired(Timer<ImageEventSender>*) { - dispatchPendingLoadEvents(); + dispatchPendingEvents(); } } diff --git a/WebCore/loader/ImageLoader.h b/WebCore/loader/ImageLoader.h index 3496f75..7f42e33 100644 --- a/WebCore/loader/ImageLoader.h +++ b/WebCore/loader/ImageLoader.h @@ -53,9 +53,10 @@ public: void setLoadManually(bool loadManually) { m_loadManually = loadManually; } + bool haveFiredBeforeLoadEvent() const { return m_firedBeforeLoad; } bool haveFiredLoadEvent() const { return m_firedLoad; } - static void dispatchPendingLoadEvents(); + static void dispatchPendingEvents(); protected: virtual void notifyFinished(CachedResource*); @@ -64,14 +65,18 @@ private: virtual void dispatchLoadEvent() = 0; virtual String sourceURI(const AtomicString&) const = 0; - friend class ImageLoadEventSender; + friend class ImageEventSender; + void dispatchPendingBeforeLoadEvent(); void dispatchPendingLoadEvent(); void setLoadingImage(CachedImage*); + void updateRenderer(); + Element* m_element; CachedResourceHandle<CachedImage> m_image; AtomicString m_failedLoadURL; + bool m_firedBeforeLoad : 1; bool m_firedLoad : 1; bool m_imageComplete : 1; bool m_loadManually : 1; diff --git a/WebCore/loader/MainResourceLoader.cpp b/WebCore/loader/MainResourceLoader.cpp index e7bdbcb..c37daef 100644 --- a/WebCore/loader/MainResourceLoader.cpp +++ b/WebCore/loader/MainResourceLoader.cpp @@ -77,7 +77,7 @@ void MainResourceLoader::receivedError(const ResourceError& error) if (!cancelled()) { ASSERT(!reachedTerminalState()); - frameLoader()->didFailToLoad(this, error); + frameLoader()->notifier()->didFailToLoad(this, error); releaseResources(); } diff --git a/WebCore/loader/PolicyCallback.h b/WebCore/loader/PolicyCallback.h index 2aa7c7c..757fff8 100644 --- a/WebCore/loader/PolicyCallback.h +++ b/WebCore/loader/PolicyCallback.h @@ -37,43 +37,43 @@ namespace WebCore { - class FormState; +class FormState; - typedef void (*NavigationPolicyDecisionFunction)(void* argument, - const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); - typedef void (*NewWindowPolicyDecisionFunction)(void* argument, - const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); - typedef void (*ContentPolicyDecisionFunction)(void* argument, PolicyAction); +typedef void (*NavigationPolicyDecisionFunction)(void* argument, + const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue); +typedef void (*NewWindowPolicyDecisionFunction)(void* argument, + const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue); +typedef void (*ContentPolicyDecisionFunction)(void* argument, PolicyAction); - class PolicyCallback { - public: - PolicyCallback(); - ~PolicyCallback(); +class PolicyCallback { +public: + PolicyCallback(); + ~PolicyCallback(); - void clear(); - void set(const ResourceRequest&, PassRefPtr<FormState>, - NavigationPolicyDecisionFunction, void* argument); - void set(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, - NewWindowPolicyDecisionFunction, void* argument); - void set(ContentPolicyDecisionFunction, void* argument); + void clear(); + void set(const ResourceRequest&, PassRefPtr<FormState>, + NavigationPolicyDecisionFunction, void* argument); + void set(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, + NewWindowPolicyDecisionFunction, void* argument); + void set(ContentPolicyDecisionFunction, void* argument); - const ResourceRequest& request() const { return m_request; } - void clearRequest(); + const ResourceRequest& request() const { return m_request; } + void clearRequest(); - void call(bool shouldContinue); - void call(PolicyAction); - void cancel(); + void call(bool shouldContinue); + void call(PolicyAction); + void cancel(); - private: - ResourceRequest m_request; - RefPtr<FormState> m_formState; - String m_frameName; +private: + ResourceRequest m_request; + RefPtr<FormState> m_formState; + String m_frameName; - NavigationPolicyDecisionFunction m_navigationFunction; - NewWindowPolicyDecisionFunction m_newWindowFunction; - ContentPolicyDecisionFunction m_contentFunction; - void* m_argument; - }; + NavigationPolicyDecisionFunction m_navigationFunction; + NewWindowPolicyDecisionFunction m_newWindowFunction; + ContentPolicyDecisionFunction m_contentFunction; + void* m_argument; +}; } // namespace WebCore diff --git a/WebCore/loader/PolicyChecker.h b/WebCore/loader/PolicyChecker.h index c667f5b..541729c 100644 --- a/WebCore/loader/PolicyChecker.h +++ b/WebCore/loader/PolicyChecker.h @@ -38,59 +38,59 @@ namespace WebCore { - class DocumentLoader; - class FormState; - class Frame; - class NavigationAction; - class ResourceError; - class ResourceResponse; - - class PolicyChecker : public Noncopyable { - public: - PolicyChecker(Frame*); - - void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>, NavigationPolicyDecisionFunction, void* argument); - void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction, void* argument); - void checkNewWindowPolicy(const NavigationAction&, NewWindowPolicyDecisionFunction, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, void* argument); - void checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction, void* argument); - - // FIXME: These are different. They could use better names. - void cancelCheck(); - void stopCheck(); - - void cannotShowMIMEType(const ResourceResponse&); - - FrameLoadType loadType() const { return m_loadType; } - void setLoadType(FrameLoadType loadType) { m_loadType = loadType; } - - bool delegateIsDecidingNavigationPolicy() const { return m_delegateIsDecidingNavigationPolicy; } - bool delegateIsHandlingUnimplementablePolicy() const { return m_delegateIsHandlingUnimplementablePolicy; } - - // FIXME: This function is a cheat. Basically, this is just an asynchronouc callback - // from the FrameLoaderClient, but this callback uses the policy types and so has to - // live on this object. In the long term, we should create a type for non-policy - // callbacks from the FrameLoaderClient and remove this vestige. I just don't have - // the heart to hack on all the platforms to make that happen right now. - void continueLoadAfterWillSubmitForm(PolicyAction); - - private: - void continueAfterNavigationPolicy(PolicyAction); - void continueAfterNewWindowPolicy(PolicyAction); - void continueAfterContentPolicy(PolicyAction); - - void handleUnimplementablePolicy(const ResourceError&); - - Frame* m_frame; - - bool m_delegateIsDecidingNavigationPolicy; - bool m_delegateIsHandlingUnimplementablePolicy; - - // This identifies the type of navigation action which prompted this load. Note - // that WebKit conveys this value as the WebActionNavigationTypeKey value - // on navigation action delegate callbacks. - FrameLoadType m_loadType; - PolicyCallback m_callback; - }; +class DocumentLoader; +class FormState; +class Frame; +class NavigationAction; +class ResourceError; +class ResourceResponse; + +class PolicyChecker : public Noncopyable { +public: + PolicyChecker(Frame*); + + void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>, NavigationPolicyDecisionFunction, void* argument); + void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction, void* argument); + void checkNewWindowPolicy(const NavigationAction&, NewWindowPolicyDecisionFunction, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, void* argument); + void checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction, void* argument); + + // FIXME: These are different. They could use better names. + void cancelCheck(); + void stopCheck(); + + void cannotShowMIMEType(const ResourceResponse&); + + FrameLoadType loadType() const { return m_loadType; } + void setLoadType(FrameLoadType loadType) { m_loadType = loadType; } + + bool delegateIsDecidingNavigationPolicy() const { return m_delegateIsDecidingNavigationPolicy; } + bool delegateIsHandlingUnimplementablePolicy() const { return m_delegateIsHandlingUnimplementablePolicy; } + + // FIXME: This function is a cheat. Basically, this is just an asynchronouc callback + // from the FrameLoaderClient, but this callback uses the policy types and so has to + // live on this object. In the long term, we should create a type for non-policy + // callbacks from the FrameLoaderClient and remove this vestige. I just don't have + // the heart to hack on all the platforms to make that happen right now. + void continueLoadAfterWillSubmitForm(PolicyAction); + +private: + void continueAfterNavigationPolicy(PolicyAction); + void continueAfterNewWindowPolicy(PolicyAction); + void continueAfterContentPolicy(PolicyAction); + + void handleUnimplementablePolicy(const ResourceError&); + + Frame* m_frame; + + bool m_delegateIsDecidingNavigationPolicy; + bool m_delegateIsHandlingUnimplementablePolicy; + + // This identifies the type of navigation action which prompted this load. Note + // that WebKit conveys this value as the WebActionNavigationTypeKey value + // on navigation action delegate callbacks. + FrameLoadType m_loadType; + PolicyCallback m_callback; +}; } // namespace WebCore diff --git a/WebCore/loader/RedirectScheduler.cpp b/WebCore/loader/RedirectScheduler.cpp index 819cbdd..c0d78ae 100644 --- a/WebCore/loader/RedirectScheduler.cpp +++ b/WebCore/loader/RedirectScheduler.cpp @@ -255,12 +255,20 @@ void RedirectScheduler::scheduleHistoryNavigation(int steps) if (!m_frame->page()) return; + // Invalid history navigations (such as history.forward() during a new load) have the side effect of cancelling any scheduled + // redirects. We also avoid the possibility of cancelling the current load by avoiding the scheduled redirection altogether. + if (!m_frame->page()->canGoBackOrForward(steps)) { + cancel(); + return; + } + schedule(new ScheduledRedirection(steps)); } void RedirectScheduler::timerFired(Timer<RedirectScheduler>*) { - ASSERT(m_frame->page()); + if (!m_frame->page()) + return; if (m_frame->page()->defersLoading()) return; @@ -277,13 +285,12 @@ void RedirectScheduler::timerFired(Timer<RedirectScheduler>*) case ScheduledRedirection::historyNavigation: if (redirection->historySteps == 0) { // Special case for go(0) from a frame -> reload only the frame - loader->urlSelected(loader->url(), "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture); + loader->urlSelected(loader->url(), "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, SendReferrer); return; } // go(i!=0) from a frame navigates into the history of the frame only, // in both IE and NS (but not in Mozilla). We can't easily do that. - if (m_frame->page()->canGoBackOrForward(redirection->historySteps)) - m_frame->page()->goBackOrForward(redirection->historySteps); + m_frame->page()->goBackOrForward(redirection->historySteps); return; case ScheduledRedirection::formSubmission: // The submitForm function will find a target frame before using the redirection timer. @@ -293,7 +300,7 @@ void RedirectScheduler::timerFired(Timer<RedirectScheduler>*) if (!redirection->formState->sourceFrame()->loader()->shouldAllowNavigation(m_frame)) return; loader->loadFrameRequest(redirection->frameRequest, redirection->lockHistory, redirection->lockBackForwardList, - redirection->event, redirection->formState); + redirection->event, redirection->formState, SendReferrer); return; } diff --git a/WebCore/loader/RedirectScheduler.h b/WebCore/loader/RedirectScheduler.h index bf076d6..005a173 100644 --- a/WebCore/loader/RedirectScheduler.h +++ b/WebCore/loader/RedirectScheduler.h @@ -39,42 +39,42 @@ namespace WebCore { - class FormState; - class Frame; - class String; +class FormState; +class Frame; +class String; - struct FrameLoadRequest; - struct ScheduledRedirection; +struct FrameLoadRequest; +struct ScheduledRedirection; - class RedirectScheduler : public Noncopyable { - public: - RedirectScheduler(Frame*); - ~RedirectScheduler(); +class RedirectScheduler : public Noncopyable { +public: + RedirectScheduler(Frame*); + ~RedirectScheduler(); - bool redirectScheduledDuringLoad(); - bool locationChangePending(); + bool redirectScheduledDuringLoad(); + bool locationChangePending(); - void scheduleRedirect(double delay, const String& url); - void scheduleLocationChange(const String& url, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false); - void scheduleFormSubmission(const FrameLoadRequest&, bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>); - void scheduleRefresh(bool userGesture = false); - void scheduleHistoryNavigation(int steps); + void scheduleRedirect(double delay, const String& url); + void scheduleLocationChange(const String& url, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false); + void scheduleFormSubmission(const FrameLoadRequest&, bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>); + void scheduleRefresh(bool userGesture = false); + void scheduleHistoryNavigation(int steps); - void startTimer(); + void startTimer(); - void cancel(bool newLoadInProgress = false); - void clear(); + void cancel(bool newLoadInProgress = false); + void clear(); - private: - void timerFired(Timer<RedirectScheduler>*); - void schedule(PassOwnPtr<ScheduledRedirection>); +private: + void timerFired(Timer<RedirectScheduler>*); + void schedule(PassOwnPtr<ScheduledRedirection>); - static bool mustLockBackForwardList(Frame* targetFrame); + static bool mustLockBackForwardList(Frame* targetFrame); - Frame* m_frame; - Timer<RedirectScheduler> m_timer; - OwnPtr<ScheduledRedirection> m_scheduledRedirection; - }; + Frame* m_frame; + Timer<RedirectScheduler> m_timer; + OwnPtr<ScheduledRedirection> m_scheduledRedirection; +}; } // namespace WebCore diff --git a/WebCore/loader/ResourceLoadNotifier.cpp b/WebCore/loader/ResourceLoadNotifier.cpp new file mode 100644 index 0000000..4cddd01 --- /dev/null +++ b/WebCore/loader/ResourceLoadNotifier.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "ResourceLoadNotifier.h" + +#include "DocumentLoader.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameLoaderClient.h" +#include "InspectorController.h" +#include "Page.h" +#include "ProgressTracker.h" +#include "ResourceLoader.h" + +namespace WebCore { + +ResourceLoadNotifier::ResourceLoadNotifier(Frame* frame) + : m_frame(frame) +{ +} + +void ResourceLoadNotifier::didReceiveAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) +{ + m_frame->loader()->client()->dispatchDidReceiveAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); +} + +void ResourceLoadNotifier::didCancelAuthenticationChallenge(ResourceLoader* loader, const AuthenticationChallenge& currentWebChallenge) +{ + m_frame->loader()->client()->dispatchDidCancelAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge); +} + +void ResourceLoadNotifier::willSendRequest(ResourceLoader* loader, ResourceRequest& clientRequest, const ResourceResponse& redirectResponse) +{ + m_frame->loader()->applyUserAgent(clientRequest); + + dispatchWillSendRequest(loader->documentLoader(), loader->identifier(), clientRequest, redirectResponse); +} + +void ResourceLoadNotifier::didReceiveResponse(ResourceLoader* loader, const ResourceResponse& r) +{ + loader->documentLoader()->addResponse(r); + + if (Page* page = m_frame->page()) + page->progress()->incrementProgress(loader->identifier(), r); + + dispatchDidReceiveResponse(loader->documentLoader(), loader->identifier(), r); +} + +void ResourceLoadNotifier::didReceiveData(ResourceLoader* loader, const char* data, int length, int lengthReceived) +{ + if (Page* page = m_frame->page()) + page->progress()->incrementProgress(loader->identifier(), data, length); + + dispatchDidReceiveContentLength(loader->documentLoader(), loader->identifier(), lengthReceived); +} + +void ResourceLoadNotifier::didFinishLoad(ResourceLoader* loader) +{ + if (Page* page = m_frame->page()) + page->progress()->completeProgress(loader->identifier()); + dispatchDidFinishLoading(loader->documentLoader(), loader->identifier()); +} + +void ResourceLoadNotifier::didFailToLoad(ResourceLoader* loader, const ResourceError& error) +{ + if (Page* page = m_frame->page()) + page->progress()->completeProgress(loader->identifier()); + + if (!error.isNull()) + m_frame->loader()->client()->dispatchDidFailLoading(loader->documentLoader(), loader->identifier(), error); +} + +void ResourceLoadNotifier::didLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString) +{ + m_frame->loader()->client()->dispatchDidLoadResourceByXMLHttpRequest(identifier, sourceString); +} + +void ResourceLoadNotifier::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request) +{ + m_frame->loader()->client()->assignIdentifierToInitialRequest(identifier, loader, request); + +#if ENABLE(INSPECTOR) + if (Page* page = m_frame->page()) + page->inspectorController()->identifierForInitialRequest(identifier, loader, request); +#endif +} + +void ResourceLoadNotifier::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) +{ + StringImpl* oldRequestURL = request.url().string().impl(); + m_frame->loader()->documentLoader()->didTellClientAboutLoad(request.url()); + + m_frame->loader()->client()->dispatchWillSendRequest(loader, identifier, request, redirectResponse); + + // If the URL changed, then we want to put that new URL in the "did tell client" set too. + if (!request.isNull() && oldRequestURL != request.url().string().impl()) + m_frame->loader()->documentLoader()->didTellClientAboutLoad(request.url()); + +#if ENABLE(INSPECTOR) + if (Page* page = m_frame->page()) + page->inspectorController()->willSendRequest(loader, identifier, request, redirectResponse); +#endif +} + +void ResourceLoadNotifier::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r) +{ + m_frame->loader()->client()->dispatchDidReceiveResponse(loader, identifier, r); + +#if ENABLE(INSPECTOR) + if (Page* page = m_frame->page()) + page->inspectorController()->didReceiveResponse(loader, identifier, r); +#endif +} + +void ResourceLoadNotifier::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length) +{ + m_frame->loader()->client()->dispatchDidReceiveContentLength(loader, identifier, length); + +#if ENABLE(INSPECTOR) + if (Page* page = m_frame->page()) + page->inspectorController()->didReceiveContentLength(loader, identifier, length); +#endif +} + +void ResourceLoadNotifier::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier) +{ + m_frame->loader()->client()->dispatchDidFinishLoading(loader, identifier); + +#if ENABLE(INSPECTOR) + if (Page* page = m_frame->page()) + page->inspectorController()->didFinishLoading(loader, identifier); +#endif +} + +void ResourceLoadNotifier::sendRemainingDelegateMessages(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response, int length, const ResourceError& error) +{ + if (!response.isNull()) + dispatchDidReceiveResponse(loader, identifier, response); + + if (length > 0) + dispatchDidReceiveContentLength(loader, identifier, length); + + if (error.isNull()) + dispatchDidFinishLoading(loader, identifier); + else + m_frame->loader()->client()->dispatchDidFailLoading(loader, identifier, error); +} + +} // namespace WebCore diff --git a/WebCore/loader/ResourceLoadNotifier.h b/WebCore/loader/ResourceLoadNotifier.h new file mode 100644 index 0000000..b09d7be --- /dev/null +++ b/WebCore/loader/ResourceLoadNotifier.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ResourceLoadNotifier_h +#define ResourceLoadNotifier_h + +#include <wtf/Noncopyable.h> + +namespace WebCore { + +class AuthenticationChallenge; +class DocumentLoader; +class Frame; +class ResourceError; +class ResourceLoader; +class ResourceResponse; +class ScriptString; +struct ResourceRequest; + +class ResourceLoadNotifier : public Noncopyable { +public: + ResourceLoadNotifier(Frame*); + + void didReceiveAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); + void didCancelAuthenticationChallenge(ResourceLoader*, const AuthenticationChallenge&); + + void willSendRequest(ResourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse); + void didReceiveResponse(ResourceLoader*, const ResourceResponse&); + void didReceiveData(ResourceLoader*, const char*, int, int lengthReceived); + void didFinishLoad(ResourceLoader*); + void didFailToLoad(ResourceLoader*, const ResourceError&); + void didLoadResourceByXMLHttpRequest(unsigned long identifier, const ScriptString& sourceString); + + void assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&); + void dispatchWillSendRequest(DocumentLoader*, unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse); + void dispatchDidReceiveResponse(DocumentLoader*, unsigned long identifier, const ResourceResponse&); + void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int length); + void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier); + + void sendRemainingDelegateMessages(DocumentLoader*, unsigned long identifier, const ResourceResponse&, int length, const ResourceError&); + +private: + Frame* m_frame; +}; + +} // namespace WebCore + +#endif // ResourceLoadNotifier_h diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp index 2dac844..fcc9f61 100644 --- a/WebCore/loader/ResourceLoader.cpp +++ b/WebCore/loader/ResourceLoader.cpp @@ -199,18 +199,18 @@ void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceRes // Protect this in this delegate method since the additional processing can do // anything including possibly derefing this; one example of this is Radar 3266216. RefPtr<ResourceLoader> protector(this); - + ASSERT(!m_reachedTerminalState); if (m_sendResourceLoadCallbacks) { if (!m_identifier) { m_identifier = m_frame->page()->progress()->createUniqueIdentifier(); - frameLoader()->assignIdentifierToInitialRequest(m_identifier, request); + frameLoader()->notifier()->assignIdentifierToInitialRequest(m_identifier, documentLoader(), request); } - frameLoader()->willSendRequest(this, request, redirectResponse); + frameLoader()->notifier()->willSendRequest(this, request, redirectResponse); } - + m_request = request; } @@ -232,7 +232,7 @@ void ResourceLoader::didReceiveResponse(const ResourceResponse& r) data->removeGeneratedFilesIfNeeded(); if (m_sendResourceLoadCallbacks) - frameLoader()->didReceiveResponse(this, m_response); + frameLoader()->notifier()->didReceiveResponse(this, m_response); } void ResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce) @@ -252,7 +252,7 @@ void ResourceLoader::didReceiveData(const char* data, int length, long long leng // However, with today's computers and networking speeds, this won't happen in practice. // Could be an issue with a giant local file. if (m_sendResourceLoadCallbacks && m_frame) - frameLoader()->didReceiveData(this, data, length, static_cast<int>(lengthReceived)); + frameLoader()->notifier()->didReceiveData(this, data, length, static_cast<int>(lengthReceived)); } void ResourceLoader::willStopBufferingData(const char* data, int length) @@ -286,7 +286,7 @@ void ResourceLoader::didFinishLoadingOnePart() return; m_calledDidFinishLoad = true; if (m_sendResourceLoadCallbacks) - frameLoader()->didFinishLoad(this); + frameLoader()->notifier()->didFinishLoad(this); } void ResourceLoader::didFail(const ResourceError& error) @@ -303,7 +303,7 @@ void ResourceLoader::didFail(const ResourceError& error) data->removeGeneratedFilesIfNeeded(); if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad) - frameLoader()->didFailToLoad(this, error); + frameLoader()->notifier()->didFailToLoad(this, error); releaseResources(); } @@ -332,7 +332,7 @@ void ResourceLoader::didCancel(const ResourceError& error) m_handle = 0; } if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad) - frameLoader()->didFailToLoad(this, error); + frameLoader()->notifier()->didFailToLoad(this, error); releaseResources(); } @@ -435,7 +435,7 @@ void ResourceLoader::didReceiveAuthenticationChallenge(const AuthenticationChall // Protect this in this delegate method since the additional processing can do // anything including possibly derefing this; one example of this is Radar 3266216. RefPtr<ResourceLoader> protector(this); - frameLoader()->didReceiveAuthenticationChallenge(this, challenge); + frameLoader()->notifier()->didReceiveAuthenticationChallenge(this, challenge); } void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChallenge& challenge) @@ -443,7 +443,7 @@ void ResourceLoader::didCancelAuthenticationChallenge(const AuthenticationChalle // Protect this in this delegate method since the additional processing can do // anything including possibly derefing this; one example of this is Radar 3266216. RefPtr<ResourceLoader> protector(this); - frameLoader()->didCancelAuthenticationChallenge(this, challenge); + frameLoader()->notifier()->didCancelAuthenticationChallenge(this, challenge); } void ResourceLoader::receivedCancellation(const AuthenticationChallenge&) |