📄 mainresourceloader.cpp
字号:
/* * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. * Copyright (C) 2008 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 "MainResourceLoader.h"#if ENABLE(OFFLINE_WEB_APPLICATIONS)#include "ApplicationCache.h"#include "ApplicationCacheGroup.h"#include "ApplicationCacheResource.h"#endif#include "DocumentLoader.h"#include "Frame.h"#include "FrameLoader.h"#include "FrameLoaderClient.h"#include "HTMLFormElement.h"#include "Page.h"#include "ResourceError.h"#include "ResourceHandle.h"#include "Settings.h"// FIXME: More that is in common with SubresourceLoader should move up into ResourceLoader.namespace WebCore {MainResourceLoader::MainResourceLoader(Frame* frame) : ResourceLoader(frame, true, true) , m_dataLoadTimer(this, &MainResourceLoader::handleDataLoadNow) , m_loadingMultipartContent(false) , m_waitingForContentPolicy(false){}MainResourceLoader::~MainResourceLoader(){}PassRefPtr<MainResourceLoader> MainResourceLoader::create(Frame* frame){ return adoptRef(new MainResourceLoader(frame));}void MainResourceLoader::receivedError(const ResourceError& error){ // Calling receivedMainResourceError will likely result in the last reference to this object to go away. RefPtr<MainResourceLoader> protect(this); RefPtr<Frame> protectFrame(m_frame); // It is important that we call FrameLoader::receivedMainResourceError before calling // FrameLoader::didFailToLoad because receivedMainResourceError clears out the relevant // document loaders. Also, receivedMainResourceError ends up calling a FrameLoadDelegate method // and didFailToLoad calls a ResourceLoadDelegate method and they need to be in the correct order. frameLoader()->receivedMainResourceError(error, true); if (!cancelled()) { ASSERT(!reachedTerminalState()); frameLoader()->didFailToLoad(this, error); releaseResources(); } ASSERT(reachedTerminalState());}void MainResourceLoader::didCancel(const ResourceError& error){ m_dataLoadTimer.stop(); // Calling receivedMainResourceError will likely result in the last reference to this object to go away. RefPtr<MainResourceLoader> protect(this); if (m_waitingForContentPolicy) { frameLoader()->cancelContentPolicyCheck(); ASSERT(m_waitingForContentPolicy); m_waitingForContentPolicy = false; deref(); // balances ref in didReceiveResponse } frameLoader()->receivedMainResourceError(error, true); ResourceLoader::didCancel(error);}ResourceError MainResourceLoader::interruptionForPolicyChangeError() const{ return frameLoader()->interruptionForPolicyChangeError(request());}void MainResourceLoader::stopLoadingForPolicyChange(){ cancel(interruptionForPolicyChangeError());}void MainResourceLoader::callContinueAfterNavigationPolicy(void* argument, const ResourceRequest& request, PassRefPtr<FormState>, bool shouldContinue){ static_cast<MainResourceLoader*>(argument)->continueAfterNavigationPolicy(request, shouldContinue);}void MainResourceLoader::continueAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue){ if (!shouldContinue) stopLoadingForPolicyChange(); deref(); // balances ref in willSendRequest}bool MainResourceLoader::isPostOrRedirectAfterPost(const ResourceRequest& newRequest, const ResourceResponse& redirectResponse){ if (newRequest.httpMethod() == "POST") return true; int status = redirectResponse.httpStatusCode(); if (((status >= 301 && status <= 303) || status == 307) && frameLoader()->initialRequest().httpMethod() == "POST") return true; return false;}void MainResourceLoader::addData(const char* data, int length, bool allAtOnce){ ResourceLoader::addData(data, length, allAtOnce); frameLoader()->receivedData(data, length);}void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const ResourceResponse& redirectResponse){ // Note that there are no asserts here as there are for the other callbacks. This is due to the // fact that this "callback" is sent when starting every load, and the state of callback // deferrals plays less of a part in this function in preventing the bad behavior deferring // callbacks is meant to prevent. ASSERT(!newRequest.isNull()); // The additional processing can do anything including possibly removing the last // reference to this object; one example of this is 3266216. RefPtr<MainResourceLoader> protect(this); // Update cookie policy base URL as URL changes, except for subframes, which use the // URL of the main frame which doesn't change when we redirect. if (frameLoader()->isLoadingMainFrame()) newRequest.setMainDocumentURL(newRequest.url()); // If we're fielding a redirect in response to a POST, force a load from origin, since // this is a common site technique to return to a page viewing some data that the POST // just modified. // Also, POST requests always load from origin, but this does not affect subresources. if (newRequest.cachePolicy() == UseProtocolCachePolicy && isPostOrRedirectAfterPost(newRequest, redirectResponse)) newRequest.setCachePolicy(ReloadIgnoringCacheData); ResourceLoader::willSendRequest(newRequest, redirectResponse); // Don't set this on the first request. It is set when the main load was started. m_documentLoader->setRequest(newRequest); // FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate // listener. But there's no way to do that in practice. So instead we cancel later if the // listener tells us to. In practice that means the navigation policy needs to be decided // synchronously for these redirect cases. ref(); // balanced by deref in continueAfterNavigationPolicy frameLoader()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this);}static bool shouldLoadAsEmptyDocument(const KURL& url){#if PLATFORM(TORCHMOBILE) return url.isEmpty() || (url.protocolIs("about") && equalIgnoringRef(url, blankURL()));#else return url.isEmpty() || url.protocolIs("about");#endif}void MainResourceLoader::continueAfterContentPolicy(PolicyAction contentPolicy, const ResourceResponse& r){ KURL url = request().url(); const String& mimeType = r.mimeType(); switch (contentPolicy) { case PolicyUse: { // Prevent remote web archives from loading because they can claim to be from any domain and thus avoid cross-domain security checks (4120255). bool isRemoteWebArchive = equalIgnoringCase("application/x-webarchive", mimeType) && !m_substituteData.isValid() && !url.isLocalFile(); if (!frameLoader()->canShowMIMEType(mimeType) || isRemoteWebArchive) { frameLoader()->cannotShowMIMEType(r); // Check reachedTerminalState since the load may have already been cancelled inside of _handleUnimplementablePolicyWithErrorCode::. if (!reachedTerminalState()) stopLoadingForPolicyChange(); return; } break; } case PolicyDownload: // m_handle can be null, e.g. when loading a substitute resource from application cache. if (!m_handle) { receivedError(cannotShowURLError()); return; } frameLoader()->client()->download(m_handle.get(), request(), m_handle.get()->request(), r); // It might have gone missing if (frameLoader()) receivedError(interruptionForPolicyChangeError()); return; case PolicyIgnore: stopLoadingForPolicyChange(); return; default: ASSERT_NOT_REACHED(); } RefPtr<MainResourceLoader> protect(this); if (r.isHTTP()) { int status = r.httpStatusCode(); if (status < 200 || status >= 300) { bool hostedByObject = frameLoader()->isHostedByObjectElement(); frameLoader()->handleFallbackContent(); // object elements are no longer rendered after we fallback, so don't // keep trying to process data from their load if (hostedByObject) cancel(); } } // we may have cancelled this load as part of switching to fallback content if (!reachedTerminalState()) ResourceLoader::didReceiveResponse(r); if (frameLoader() && !frameLoader()->isStopping()) if (m_substituteData.isValid()) { if (m_substituteData.content()->size()) didReceiveData(m_substituteData.content()->data(), m_substituteData.content()->size(), m_substituteData.content()->size(), true); if (frameLoader() && !frameLoader()->isStopping()) didFinishLoading(); } else if (shouldLoadAsEmptyDocument(url) || frameLoader()->representationExistsForURLScheme(url.protocol())) didFinishLoading();}void MainResourceLoader::callContinueAfterContentPolicy(void* argument, PolicyAction policy){ static_cast<MainResourceLoader*>(argument)->continueAfterContentPolicy(policy);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -