blob: 20123f4a4e4b697675c8fd7a4f68f0fce9196f33 [file] [log] [blame]
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* 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.
*/
#import "config.h"
#import "FrameLoader.h"
#import "BlockExceptions.h"
#import "Cache.h"
#import "Chrome.h"
#import "DOMElementInternal.h"
#import "Document.h"
#import "DocumentLoader.h"
#import "FloatRect.h"
#import "FormDataStreamMac.h"
#import "FormState.h"
#import "FrameLoadRequest.h"
#import "FrameLoaderClient.h"
#import "FrameMac.h"
#import "FramePrivate.h"
#import "FrameTree.h"
#import "FrameView.h"
#import "HTMLFormElement.h"
#import "HTMLFrameElement.h"
#import "HTMLNames.h"
#import "LoaderNSURLExtras.h"
#import "LoaderNSURLRequestExtras.h"
#import "MainResourceLoader.h"
#import "NavigationAction.h"
#import "Page.h"
#import "PageState.h"
#import "Plugin.h"
#import "ResourceResponse.h"
#import "ResourceResponseMac.h"
#import "SubresourceLoader.h"
#import "SystemTime.h"
#import "TextResourceDecoder.h"
#import "WebCoreFrameBridge.h"
#import "WebCoreIconDatabaseBridge.h"
#import "WebCorePageState.h"
#import "WebCoreSystemInterface.h"
#import "WebDataProtocol.h"
#import "Widget.h"
#import "WindowFeatures.h"
#import <kjs/JSLock.h>
#import <wtf/Assertions.h>
namespace WebCore {
using namespace HTMLNames;
void FrameLoader::load(const FrameLoadRequest& request, bool userGesture, Event* event,
Element* submitForm, const HashMap<String, String>& formValues)
{
String referrer;
String argsReferrer = request.resourceRequest().httpReferrer();
if (!argsReferrer.isEmpty())
referrer = argsReferrer;
else
referrer = m_outgoingReferrer;
bool hideReferrer;
if (!canLoad(request.resourceRequest().url().getNSURL(), referrer, hideReferrer))
return;
if (hideReferrer)
referrer = String();
Frame* targetFrame = m_frame->tree()->find(request.frameName());
if (!canTarget(targetFrame))
return;
if (request.resourceRequest().httpMethod() != "POST") {
FrameLoadType loadType;
if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
loadType = FrameLoadTypeReload;
else if (!userGesture)
loadType = FrameLoadTypeInternal;
else
loadType = FrameLoadTypeStandard;
load(request.resourceRequest().url(), referrer, loadType,
request.frameName(), event, submitForm, formValues);
} else
post(request.resourceRequest().url(), referrer, request.frameName(),
request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues);
if (targetFrame && targetFrame != m_frame)
targetFrame->page()->chrome()->focus();
}
void FrameLoader::load(const KURL& URL, const String& referrer, FrameLoadType newLoadType,
const String& frameName, Event* event, Element* form, const HashMap<String, String>& values)
{
bool isFormSubmission = !values.isEmpty();
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL.getNSURL()];
setHTTPReferrer(request, referrer);
addExtraFieldsToRequest(request, true, event || isFormSubmission);
if (newLoadType == FrameLoadTypeReload)
[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
ASSERT(newLoadType != FrameLoadTypeSame);
NavigationAction action(URL, newLoadType, isFormSubmission, event);
RefPtr<FormState> formState;
if (form && !values.isEmpty())
formState = FormState::create(form, values, m_frame);
if (!frameName.isEmpty()) {
if (Frame* targetFrame = m_frame->tree()->find(frameName))
targetFrame->loader()->load(URL, referrer, newLoadType, String(), event, form, values);
else
checkNewWindowPolicy(action, request, formState.release(), frameName);
[request release];
return;
}
RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
bool sameURL = m_client->shouldTreatURLAsSameAsCurrent(URL);
// Make sure to do scroll to anchor processing even if the URL is
// exactly the same so pages with '#' links and DHTML side effects
// work properly.
if (!isFormSubmission
&& newLoadType != FrameLoadTypeReload
&& newLoadType != FrameLoadTypeSame
&& !shouldReload(URL, url())
// We don't want to just scroll if a link from within a
// frameset is trying to reload the frameset into _top.
&& !m_frame->isFrameSet()) {
// Just do anchor navigation within the existing content.
// We don't do this if we are submitting a form, explicitly reloading,
// currently displaying a frameset, or if the new URL does not have a fragment.
// These rules are based on what KHTML was doing in KHTMLPart::openURL.
// FIXME: What about load types other than Standard and Reload?
oldDocumentLoader->setTriggeringAction(action);
stopPolicyCheck();
checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
callContinueFragmentScrollAfterNavigationPolicy, this);
} else {
// must grab this now, since this load may stop the previous load and clear this flag
bool isRedirect = m_quickRedirectComing;
load(request, action, newLoadType, formState.release());
if (isRedirect) {
m_quickRedirectComing = false;
if (m_provisionalDocumentLoader)
m_provisionalDocumentLoader->setIsClientRedirect(true);
} else if (sameURL)
// Example of this case are sites that reload the same URL with a different cookie
// driving the generated content, or a master frame with links that drive a target
// frame, where the user has clicked on the same link repeatedly.
m_loadType = FrameLoadTypeSame;
}
[request release];
}
void FrameLoader::load(NSURLRequest *request)
{
// FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
m_loadType = FrameLoadTypeStandard;
load(m_client->createDocumentLoader(request).get());
}
void FrameLoader::load(NSURLRequest *request, const String& frameName)
{
if (frameName.isEmpty()) {
load(request);
return;
}
Frame* frame = m_frame->tree()->find(frameName);
if (frame) {
frame->loader()->load(request);
return;
}
checkNewWindowPolicy(NavigationAction([request URL], NavigationTypeOther),
request, 0, frameName);
}
void FrameLoader::load(NSURLRequest *request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState)
{
RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request);
setPolicyDocumentLoader(loader.get());
loader->setTriggeringAction(action);
if (m_documentLoader)
loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
load(loader.get(), type, formState);
}
void FrameLoader::load(DocumentLoader* newDocumentLoader)
{
stopPolicyCheck();
setPolicyDocumentLoader(newDocumentLoader);
NSMutableURLRequest *r = newDocumentLoader->request();
addExtraFieldsToRequest(r, true, false);
FrameLoadType type;
if (m_client->shouldTreatURLAsSameAsCurrent([newDocumentLoader->originalRequest() URL])) {
[r setCachePolicy:NSURLRequestReloadIgnoringCacheData];
type = FrameLoadTypeSame;
} else
type = FrameLoadTypeStandard;
if (m_documentLoader)
newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
// When we loading alternate content for an unreachable URL that we're
// visiting in the b/f list, we treat it as a reload so the b/f list
// is appropriately maintained.
if (shouldReloadToHandleUnreachableURL(newDocumentLoader->originalRequest())) {
ASSERT(type == FrameLoadTypeStandard);
type = FrameLoadTypeReload;
}
load(newDocumentLoader, type, 0);
}
void FrameLoader::load(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> formState)
{
ASSERT(m_client->hasWebView());
// Unfortunately the view must be non-nil, this is ultimately due
// to parser requiring a FrameView. We should fix this dependency.
ASSERT(m_client->hasFrameView());
m_policyLoadType = type;
if (Frame* parent = m_frame->tree()->parent())
loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
stopPolicyCheck();
setPolicyDocumentLoader(loader);
checkNavigationPolicy(loader->request(), loader, formState,
callContinueLoadAfterNavigationPolicy, this);
}
bool FrameLoader::canLoad(NSURL *URL, const String& referrer, bool& hideReferrer)
{
bool referrerIsWebURL = referrer.startsWith("http:", false) || referrer.startsWith("https:", false);
bool referrerIsLocalURL = referrer.startsWith("file:", false) || referrer.startsWith("applewebdata:");
bool URLIsFileURL = [URL scheme] && [[URL scheme] compare:@"file" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
bool referrerIsSecureURL = referrer.startsWith("https:", false);
bool URLIsSecureURL = [URL scheme] && [[URL scheme] compare:@"https" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
hideReferrer = !referrerIsWebURL || (referrerIsSecureURL && !URLIsSecureURL);
return !URLIsFileURL || referrerIsLocalURL;
}
bool FrameLoader::startLoadingMainResource(NSMutableURLRequest *request, id identifier)
{
ASSERT(!m_mainResourceLoader);
m_mainResourceLoader = MainResourceLoader::create(m_frame);
m_mainResourceLoader->setIdentifier(identifier);
addExtraFieldsToRequest(request, true, false);
if (!m_mainResourceLoader->load(request)) {
// FIXME: If this should really be caught, we should just ASSERT this doesn't happen;
// should it be caught by other parts of WebKit or other parts of the app?
LOG_ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level", [request URL]);
m_mainResourceLoader = 0;
return false;
}
return true;
}
// FIXME: Poor method name; also, why is this not part of startProvisionalLoad:?
void FrameLoader::startLoading()
{
m_provisionalDocumentLoader->prepareForLoadStart();
if (m_mainResourceLoader)
return;
m_client->clearLoadingFromPageCache(m_provisionalDocumentLoader.get());
id identifier = m_client->dispatchIdentifierForInitialRequest
(m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
if (!startLoadingMainResource(m_provisionalDocumentLoader->actualRequest(), identifier))
m_provisionalDocumentLoader->updateLoading();
}
void FrameLoader::cancelMainResourceLoad(NSError *error)
{
m_mainResourceLoader->cancel(error);
}
id FrameLoader::identifierForInitialRequest(NSURLRequest *clientRequest)
{
return m_client->dispatchIdentifierForInitialRequest(activeDocumentLoader(), clientRequest);
}
void FrameLoader::applyUserAgent(NSMutableURLRequest *request)
{
static String lastUserAgent;
static RetainPtr<NSString> lastUserAgentNSString;
String userAgent = client()->userAgent();
ASSERT(!userAgent.isNull());
if (userAgent != lastUserAgent) {
lastUserAgent = userAgent;
lastUserAgentNSString = userAgent;
}
[request setValue:lastUserAgentNSString.get() forHTTPHeaderField:@"User-Agent"];
}
NSURLRequest *FrameLoader::willSendRequest(ResourceLoader* loader, NSMutableURLRequest *clientRequest, NSURLResponse *redirectResponse)
{
applyUserAgent(clientRequest);
return m_client->dispatchWillSendRequest(activeDocumentLoader(), loader->identifier(), clientRequest, redirectResponse);
}
void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, NSURLAuthenticationChallenge *currentWebChallenge)
{
m_client->dispatchDidReceiveAuthenticationChallenge(activeDocumentLoader(), loader->identifier(), currentWebChallenge);
}
void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, NSURLAuthenticationChallenge *currentWebChallenge)
{
m_client->dispatchDidCancelAuthenticationChallenge(activeDocumentLoader(), loader->identifier(), currentWebChallenge);
}
void FrameLoader::didReceiveResponse(ResourceLoader* loader, NSURLResponse *r)
{
activeDocumentLoader()->addResponse(r);
m_client->incrementProgress(loader->identifier(), r);
m_client->dispatchDidReceiveResponse(activeDocumentLoader(), loader->identifier(), r);
}
void FrameLoader::didReceiveData(ResourceLoader* loader, NSData *data, int lengthReceived)
{
m_client->incrementProgress(loader->identifier(), data);
m_client->dispatchDidReceiveContentLength(activeDocumentLoader(), loader->identifier(), lengthReceived);
}
void FrameLoader::didFailToLoad(ResourceLoader* loader, NSError *error)
{
m_client->completeProgress(loader->identifier());
if (error)
m_client->dispatchDidFailLoading(activeDocumentLoader(), loader->identifier(), error);
}
NSURLRequest *FrameLoader::originalRequest() const
{
return activeDocumentLoader()->originalRequestCopy();
}
void FrameLoader::receivedMainResourceError(NSError *error, bool isComplete)
{
// Retain because the stop may release the last reference to it.
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.
stop();
if (m_client->shouldFallBack(error))
handleFallbackContent();
}
if (m_state == FrameStateProvisional) {
NSURL *failedURL = [m_provisionalDocumentLoader->originalRequestCopy() URL];
didNotOpenURL(failedURL);
// 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.
Document* document = m_frame->document();
if (document)
document->setInPageCache(false);
m_client->invalidateCurrentItemPageCache();
// 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
// the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
// not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
// has ended.
if (m_sentRedirectNotification)
clientRedirectCancelledOrFinished(false);
}
loader->mainReceivedError(error, isComplete);
}
void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
NSURLRequest *request, PassRefPtr<FormState>)
{
FrameLoader* loader = static_cast<FrameLoader*>(argument);
loader->continueFragmentScrollAfterNavigationPolicy(request);
}
void FrameLoader::continueFragmentScrollAfterNavigationPolicy(NSURLRequest *request)
{
if (!request)
return;
NSURL *URL = [request URL];
bool isRedirect = m_quickRedirectComing;
m_quickRedirectComing = false;
m_documentLoader->replaceRequestURLForAnchorScroll(URL);
if (!isRedirect && !m_client->shouldTreatURLAsSameAsCurrent(URL)) {
// NB: must happen after _setURL, since we add based on the current request.
// Must also happen before we openURL and displace the scroll position, since
// adding the BF item will save away scroll state.
// NB2: If we were loading a long, slow doc, and the user anchor nav'ed before
// it was done, currItem is now set the that slow doc, and prevItem is whatever was
// before it. Adding the b/f item will bump the slow doc down to prevItem, even
// though its load is not yet done. I think this all works out OK, for one because
// we have already saved away the scroll and doc state for the long slow load,
// but it's not an obvious case.
m_client->addHistoryItemForFragmentScroll();
}
scrollToAnchor(URL);
if (!isRedirect)
// This will clear previousItem from the rest of the frame tree that didn't
// doing any loading. We need to make a pass on this now, since for anchor nav
// we'll not go through a real load and reach Completed state.
checkLoadComplete();
m_client->dispatchDidChangeLocationWithinPage();
m_client->didFinishLoad();
}
void FrameLoader::opened()
{
if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
m_client->updateHistoryAfterClientRedirect();
if (m_client->isLoadingFromPageCache(m_documentLoader.get())) {
// Force a layout to update view size and thereby update scrollbars.
m_client->forceLayout();
const ResponseVector& responses = m_documentLoader->responses();
size_t count = responses.size();
for (size_t i = 0; i < count; i++) {
NSURLResponse *response = responses[i].get();
// FIXME: If the WebKit client changes or cancels the request, this is not respected.
NSError *error;
id identifier;
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[response URL]];
requestFromDelegate(request, identifier, error);
sendRemainingDelegateMessages(identifier, response, (unsigned)[response expectedContentLength], error);
[request release];
}
m_client->loadedFromPageCache();
m_documentLoader->setPrimaryLoadComplete(true);
// FIXME: Why only this frame and not parent frames?
checkLoadCompleteForThisFrame();
}
}
void FrameLoader::commitProvisionalLoad(NSDictionary *pageCache)
{
RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
if (m_loadType != FrameLoadTypeReplace)
closeOldDataSources();
if (!pageCache)
m_client->makeRepresentation(pdl.get());
transitionToCommitted(pageCache);
// 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
// the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are
// just about to commit a new page, there cannot possibly be a pending redirect at this point.
if (m_sentRedirectNotification)
clientRedirectCancelledOrFinished(false);
WebCorePageState *pageState = [pageCache objectForKey:WebCorePageCacheStateKey];
if (PageState* frameState = [pageState impl]) {
open(*frameState);
frameState->clear();
} else {
NSURLResponse *response = pdl->response();
NSURL *URL = [pdl->request() _webDataRequestBaseURL];
if (!URL)
URL = [response URL];
if (!URL || urlIsEmpty(URL))
URL = [NSURL URLWithString:@"about:blank"];
m_responseMIMEType = [response MIMEType];
if (didOpenURL(URL)) {
if ([response isKindOfClass:[NSHTTPURLResponse class]])
if (NSString *refresh = [[(NSHTTPURLResponse *)response allHeaderFields] objectForKey:@"Refresh"])
m_responseRefreshHeader = refresh;
m_responseModifiedHeader = [wkGetNSURLResponseLastModifiedDate(response)
descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
}
}
opened();
}
NSURLRequest *FrameLoader::initialRequest() const
{
return activeDocumentLoader()->initialRequest();
}
void FrameLoader::receivedData(NSData *data)
{
activeDocumentLoader()->receivedData(data);
}
void FrameLoader::setRequest(NSURLRequest *request)
{
activeDocumentLoader()->setRequest(request);
}
void FrameLoader::setResponse(NSURLResponse *response)
{
activeDocumentLoader()->setResponse(response);
}
void FrameLoader::mainReceivedError(NSError *error, bool isComplete)
{
activeDocumentLoader()->mainReceivedError(error, isComplete);
}
void FrameLoader::notifyIconChanged()
{
ASSERT([[WebCoreIconDatabaseBridge sharedInstance] _isEnabled]);
NSImage *icon = [[WebCoreIconDatabaseBridge sharedInstance]
iconForPageURL:urlOriginalDataAsString(activeDocumentLoader()->URL().getNSURL())
withSize:NSMakeSize(16, 16)];
m_client->dispatchDidReceiveIcon(icon);
}
NSError *FrameLoader::cancelledError(NSURLRequest *request) const
{
return m_client->cancelledError(request);
}
NSError *FrameLoader::fileDoesNotExistError(NSURLResponse *response) const
{
return m_client->fileDoesNotExistError(response);
}
bool FrameLoader::willUseArchive(ResourceLoader* loader, NSURLRequest *request, NSURL *originalURL) const
{
return m_client->willUseArchive(loader, request, originalURL);
}
void FrameLoader::handleUnimplementablePolicy(NSError *error)
{
m_delegateIsHandlingUnimplementablePolicy = true;
m_client->dispatchUnableToImplementPolicy(error);
m_delegateIsHandlingUnimplementablePolicy = false;
}
void FrameLoader::cannotShowMIMEType(NSURLResponse *response)
{
handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
}
NSError *FrameLoader::interruptionForPolicyChangeError(NSURLRequest *request)
{
return m_client->interruptForPolicyChangeError(request);
}
void FrameLoader::checkNavigationPolicy(NSURLRequest *newRequest,
NavigationPolicyDecisionFunction function, void* argument)
{
checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
}
void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
{
m_policyCheck.set(function, argument);
m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
MIMEType, activeDocumentLoader()->request());
}
bool FrameLoader::shouldReloadToHandleUnreachableURL(NSURLRequest *request)
{
NSURL *unreachableURL = [request _webDataRequestUnreachableURL];
if (unreachableURL == nil)
return false;
if (!isBackForwardLoadType(m_policyLoadType))
return false;
// We only treat unreachableURLs specially during the delegate callbacks
// for provisional load errors and navigation policy decisions. The former
// case handles well-formed URLs that can't be loaded, and the latter
// case handles malformed URLs and unknown schemes. Loading alternate content
// at other times behaves like a standard load.
DocumentLoader* compareDocumentLoader = 0;
if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
compareDocumentLoader = m_policyDocumentLoader.get();
else if (m_delegateIsHandlingProvisionalLoadError)
compareDocumentLoader = m_provisionalDocumentLoader.get();
return compareDocumentLoader && [unreachableURL isEqual:[compareDocumentLoader->request() URL]];
}
void FrameLoader::reloadAllowingStaleData(const String& encoding)
{
if (!m_documentLoader)
return;
NSMutableURLRequest *request = [m_documentLoader->request() mutableCopy];
KURL unreachableURL = m_documentLoader->unreachableURL();
if (!unreachableURL.isEmpty())
[request setURL:unreachableURL.getNSURL()];
[request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request);
setPolicyDocumentLoader(loader.get());
[request release];
loader->setOverrideEncoding(encoding);
load(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
}
void FrameLoader::reload()
{
if (!m_documentLoader)
return;
NSMutableURLRequest *initialRequest = m_documentLoader->request();
// If a window is created by javascript, its main frame can have an empty but non-nil URL.
// Reloading in this case will lose the current contents (see 4151001).
if ([[[initialRequest URL] absoluteString] length] == 0)
return;
// Replace error-page URL with the URL we were trying to reach.
NSURL *unreachableURL = [initialRequest _webDataRequestUnreachableURL];
if (unreachableURL != nil)
initialRequest = [NSURLRequest requestWithURL:unreachableURL];
RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest);
setPolicyDocumentLoader(loader.get());
NSMutableURLRequest *request = loader->request();
[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
// If we're about to re-post, set up action so the application can warn the user.
if ([[request HTTPMethod] isEqualToString:@"POST"])
loader->setTriggeringAction(NavigationAction([request URL], NavigationTypeFormResubmitted));
loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
load(loader.get(), FrameLoadTypeReload, 0);
}
void FrameLoader::committedLoad(DocumentLoader* loader, NSData *data)
{
m_client->committedLoad(loader, data);
}
void FrameLoader::setMainDocumentError(DocumentLoader* loader, NSError *error)
{
m_client->setMainDocumentError(loader, error);
}
void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, NSError *error)
{
loader->setPrimaryLoadComplete(true);
m_client->dispatchDidLoadMainResource(activeDocumentLoader());
checkLoadComplete();
}
void FrameLoader::didChangeTitle(DocumentLoader* loader)
{
m_client->didChangeTitle(loader);
// The title doesn't get communicated to the WebView until we are committed.
if (loader->isCommitted())
if (NSURL *URLForHistory = canonicalURL(loader->URLForHistory().getNSURL())) {
// Must update the entries in the back-forward list too.
// This must go through the WebFrame because it has the right notion of the current b/f item.
m_client->setTitle(loader->title(), URLForHistory);
m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
m_client->dispatchDidReceiveTitle(loader->title());
}
}
void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, NSURLRequest *request,
PassRefPtr<FormState> formState, const String& frameName)
{
m_policyCheck.set(request, formState, frameName,
callContinueLoadAfterNewWindowPolicy, this);
m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
action, request, frameName);
}
void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
{
PolicyCheck check = m_policyCheck;
m_policyCheck.clear();
switch (policy) {
case PolicyIgnore:
check.clearRequest();
break;
case PolicyDownload:
m_client->startDownload(check.request());
check.clearRequest();
break;
case PolicyUse:
break;
}
check.call();
}
void FrameLoader::checkNavigationPolicy(NSURLRequest *request, DocumentLoader* loader,
PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
{
NavigationAction action = loader->triggeringAction();
if (action.isEmpty()) {
action = NavigationAction([request URL], NavigationTypeOther);
loader->setTriggeringAction(action);
}
// Don't ask more than once for the same request or if we are loading an empty URL.
// This avoids confusion on the part of the client.
if ([request isEqual:loader->lastCheckedRequest()] || urlIsEmpty([request URL])) {
function(argument, request, 0);
return;
}
// We are always willing to show alternate content for unreachable URLs;
// treat it like a reload so it maintains the right state for b/f list.
if ([request _webDataRequestUnreachableURL] != nil) {
if (isBackForwardLoadType(m_policyLoadType))
m_policyLoadType = FrameLoadTypeReload;
function(argument, request, 0);
return;
}
loader->setLastCheckedRequest(request);
m_policyCheck.set(request, formState, function, argument);
m_delegateIsDecidingNavigationPolicy = true;
m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
action, request);
m_delegateIsDecidingNavigationPolicy = false;
}
void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
{
PolicyCheck check = m_policyCheck;
m_policyCheck.clear();
switch (policy) {
case PolicyIgnore:
check.clearRequest();
break;
case PolicyDownload:
m_client->startDownload(check.request());
check.clearRequest();
break;
case PolicyUse:
if (!m_client->canHandleRequest(check.request())) {
handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
check.clearRequest();
}
break;
}
check.call();
}
void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
NSURLRequest *request, PassRefPtr<FormState> formState)
{
FrameLoader* loader = static_cast<FrameLoader*>(argument);
loader->continueLoadAfterNavigationPolicy(request, formState);
}
void FrameLoader::continueLoadAfterNavigationPolicy(NSURLRequest *request,
PassRefPtr<FormState> formState)
{
// If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
// nil policyDataSource because loading the alternate page will have passed
// through this method already, nested; otherwise, policyDataSource should still be set.
ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
BOOL isTargetItem = m_client->provisionalItemIsTarget();
// Two reasons we can't continue:
// 1) Navigation policy delegate said we can't so request is nil. A primary case of this
// is the user responding Cancel to the form repost nag sheet.
// 2) User responded Cancel to an alert popped up by the before unload event handler.
// The "before unload" event handler runs only for the main frame.
bool canContinue = request && (!isLoadingMainFrame() || Mac(m_frame)->shouldClose());
if (!canContinue) {
// If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we
// need to report that the client redirect was cancelled.
if (m_quickRedirectComing)
clientRedirectCancelledOrFinished(false);
setPolicyDocumentLoader(0);
// If the navigation request came from the back/forward menu, and we punt on it, we have the
// problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
// we only do this when punting a navigation for the target frame or top-level frame.
if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
m_client->resetBackForwardList();
return;
}
FrameLoadType type = m_policyLoadType;
stopAllLoaders();
setProvisionalDocumentLoader(m_policyDocumentLoader.get());
m_loadType = type;
setState(FrameStateProvisional);
setPolicyDocumentLoader(0);
if (isBackForwardLoadType(type) && m_client->loadProvisionalItemFromPageCache())
return;
if (formState)
m_client->dispatchWillSubmitForm(&FrameLoader::continueAfterWillSubmitForm, formState);
else
continueAfterWillSubmitForm();
}
void FrameLoader::transitionToCommitted(NSDictionary *pageCache)
{
ASSERT(m_client->hasWebView());
ASSERT(m_state == FrameStateProvisional);
if (m_state != FrameStateProvisional)
return;
m_client->setCopiesOnScroll();
m_client->updateHistoryForCommit();
// 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,
// or the two will stomp each other.
DocumentLoader* pdl = m_provisionalDocumentLoader.get();
closeDocument();
if (pdl != m_provisionalDocumentLoader)
return;
commitProvisionalLoad();
// Handle adding the URL to the back/forward list.
DocumentLoader* dl = m_documentLoader.get();
String ptitle = dl->title();
switch (m_loadType) {
case FrameLoadTypeForward:
case FrameLoadTypeBack:
case FrameLoadTypeIndexedBackForward:
if (m_client->hasBackForwardList()) {
m_client->updateHistoryForBackForwardNavigation();
// Create a document view for this document, or used the cached view.
if (pageCache)
m_client->setDocumentViewFromPageCache(pageCache);
else
m_client->makeDocumentView();
}
break;
case FrameLoadTypeReload:
case FrameLoadTypeSame:
case FrameLoadTypeReplace:
m_client->updateHistoryForReload();
m_client->makeDocumentView();
break;
// FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
case FrameLoadTypeReloadAllowingStaleData:
m_client->makeDocumentView();
break;
case FrameLoadTypeStandard:
m_client->updateHistoryForStandardLoad();
m_client->makeDocumentView();
break;
case FrameLoadTypeInternal:
m_client->updateHistoryForInternalLoad();
m_client->makeDocumentView();
break;
// FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
// An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
default:
ASSERT_NOT_REACHED();
}
// Tell the client we've committed this URL.
ASSERT(m_client->hasFrameView());
m_client->dispatchDidCommitLoad();
// If we have a title let the WebView know about it.
if (!ptitle.isNull())
m_client->dispatchDidReceiveTitle(ptitle);
}
void FrameLoader::checkLoadCompleteForThisFrame()
{
ASSERT(m_client->hasWebView());
switch (m_state) {
case FrameStateProvisional: {
if (m_delegateIsHandlingProvisionalLoadError)
return;
RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
// If we've received any errors we may be stuck in the provisional state and actually complete.
NSError *error = pdl->mainDocumentError();
if (!error)
return;
// Check all children first.
LoadErrorResetToken *resetToken = m_client->tokenForLoadErrorReset();
bool shouldReset = true;
if (!pdl->isLoadingInAPISense()) {
m_delegateIsHandlingProvisionalLoadError = true;
m_client->dispatchDidFailProvisionalLoad(error);
m_delegateIsHandlingProvisionalLoadError = false;
// FIXME: can stopping loading here possibly have any effect, if isLoading is false,
// which it must be to be in this branch of the if? And is it OK to just do a full-on
// stopAllLoaders instead of stopLoadingSubframes?
stopLoadingSubframes();
pdl->stopLoading();
// Finish resetting the load state, but only if another load hasn't been started by the
// delegate callback.
if (pdl == m_provisionalDocumentLoader)
clearProvisionalLoad();
else if (m_documentLoader) {
KURL unreachableURL = m_documentLoader->unreachableURL();
if (!unreachableURL.isEmpty() && unreachableURL == [pdl->request() URL])
shouldReset = false;
}
}
if (shouldReset)
m_client->resetAfterLoadError(resetToken);
else
m_client->doNotResetAfterLoadError(resetToken);
return;
}
case FrameStateCommittedPage: {
DocumentLoader* dl = m_documentLoader.get();
if (dl->isLoadingInAPISense())
return;
markLoadComplete();
// FIXME: Is this subsequent work important if we already navigated away?
// Maybe there are bugs because of that, or extra work we can skip because
// the new page is ready.
m_client->forceLayoutForNonHTML();
// If the user had a scroll point, scroll to it, overriding the anchor point if any.
if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload)
&& m_client->hasBackForwardList())
m_client->restoreScrollPositionAndViewState();
NSError *error = dl->mainDocumentError();
if (error)
m_client->dispatchDidFailLoad(error);
else
m_client->dispatchDidFinishLoad();
m_client->progressCompleted();
return;
}
case FrameStateComplete:
// 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_client->frameLoadCompleted();
return;
}
ASSERT_NOT_REACHED();
}
void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
NSURLRequest *request, PassRefPtr<FormState> formState, const String& frameName)
{
FrameLoader* loader = static_cast<FrameLoader*>(argument);
loader->continueLoadAfterNewWindowPolicy(request, formState, frameName);
}
void FrameLoader::continueLoadAfterNewWindowPolicy(NSURLRequest *request,
PassRefPtr<FormState> formState, const String& frameName)
{
if (!request)
return;
RefPtr<Frame> frame = m_frame;
RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(nil);
if (!mainFrame)
return;
mainFrame->tree()->setName(frameName);
mainFrame->loader()->m_client->dispatchShow();
mainFrame->loader()->setOpener(frame.get());
mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
}
void FrameLoader::sendRemainingDelegateMessages(id identifier, NSURLResponse *response, unsigned length, NSError *error)
{
if (response)
m_client->dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
if (length > 0)
m_client->dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
if (!error)
m_client->dispatchDidFinishLoading(m_documentLoader.get(), identifier);
else
m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
}
NSURLRequest *FrameLoader::requestFromDelegate(NSURLRequest *request, id& identifier, NSError *& error)
{
ASSERT(request != nil);
identifier = m_client->dispatchIdentifierForInitialRequest(m_documentLoader.get(), request);
NSURLRequest *newRequest = m_client->dispatchWillSendRequest(m_documentLoader.get(), identifier, request, nil);
if (newRequest == nil)
error = m_client->cancelledError(request);
else
error = nil;
return newRequest;
}
void FrameLoader::loadedResourceFromMemoryCache(NSURLRequest *request, NSURLResponse *response, int length)
{
if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
return;
id identifier;
NSError *error;
requestFromDelegate(request, identifier, error);
sendRemainingDelegateMessages(identifier, response, length, error);
}
void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, const FormData& formData,
const String& contentType, Event* event, Element* form, const HashMap<String, String>& formValues)
{
// When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
// This prevents a potential bug which may cause a page with a form that uses itself
// as an action to be returned from the cache without submitting.
// FIXME: Where's the code that implements what the comment above says?
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL.getNSURL()];
addExtraFieldsToRequest(request, true, true);
setHTTPReferrer(request, referrer);
[request setHTTPMethod:@"POST"];
setHTTPBody(request, formData);
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
NavigationAction action(URL, FrameLoadTypeStandard, true, event);
RefPtr<FormState> formState;
if (form && !formValues.isEmpty())
formState = FormState::create(form, formValues, m_frame);
if (!frameName.isEmpty()) {
if (Frame* targetFrame = m_frame->tree()->find(frameName))
targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
else
checkNewWindowPolicy(action, request, formState.release(), frameName);
} else
load(request, action, FrameLoadTypeStandard, formState.release());
[request release];
}
void FrameLoader::detachFromParent()
{
RefPtr<Frame> protect(m_frame);
closeDocument();
stopAllLoaders();
m_client->detachedFromParent1();
detachChildren();
m_client->detachedFromParent2();
setDocumentLoader(0);
m_client->detachedFromParent3();
if (Frame* parent = m_frame->tree()->parent())
parent->tree()->removeChild(m_frame);
m_frame->setView(0);
[Mac(m_frame)->bridge() close];
m_client->detachedFromParent4();
}
void FrameLoader::addExtraFieldsToRequest(NSMutableURLRequest *request, bool mainResource, bool alwaysFromRequest)
{
applyUserAgent(request);
if (m_loadType == FrameLoadTypeReload)
[request setValue:@"max-age=0" forHTTPHeaderField:@"Cache-Control"];
// Don't set the cookie policy URL if it's already been set.
if (![request mainDocumentURL]) {
if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
[request setMainDocumentURL:[request URL]];
else
[request setMainDocumentURL:m_frame->page()->mainFrame()->loader()->url().getNSURL()];
}
if (mainResource)
[request setValue:@"text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" forHTTPHeaderField:@"Accept"];
}
bool FrameLoader::isReloading() const
{
return [documentLoader()->request() cachePolicy] == NSURLRequestReloadIgnoringCacheData;
}
String FrameLoader::referrer() const
{
return [documentLoader()->request() valueForHTTPHeaderField:@"Referer"];
}
void FrameLoader::loadEmptyDocumentSynchronously()
{
NSURL *url = [[NSURL alloc] initWithString:@""];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
load(request);
[request release];
[url release];
}
void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, Vector<char>& data, ResourceResponse& r)
{
NSURL *URL = request.url().getNSURL();
// Since this is a subresource, we can load any URL (we ignore the return value).
// But we still want to know whether we should hide the referrer or not, so we call the canLoadURL method.
String referrer = m_outgoingReferrer;
bool hideReferrer;
canLoad(URL, referrer, hideReferrer);
if (hideReferrer)
referrer = String();
NSMutableURLRequest *initialRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
[initialRequest setTimeoutInterval:10];
[initialRequest setHTTPMethod:request.httpMethod()];
if (!request.httpBody().isEmpty())
setHTTPBody(initialRequest, request.httpBody());
HTTPHeaderMap::const_iterator end = request.httpHeaderFields().end();
for (HTTPHeaderMap::const_iterator it = request.httpHeaderFields().begin(); it != end; ++it)
[initialRequest addValue:it->second forHTTPHeaderField:it->first];
if (isConditionalRequest(initialRequest))
[initialRequest setCachePolicy:NSURLRequestReloadIgnoringCacheData];
else
[initialRequest setCachePolicy:[documentLoader()->request() cachePolicy]];
if (!referrer.isEmpty())
setHTTPReferrer(initialRequest, referrer);
[initialRequest setMainDocumentURL:[m_frame->page()->mainFrame()->loader()->documentLoader()->request() URL]];
applyUserAgent(initialRequest);
NSError *error = nil;
id identifier = nil;
NSURLRequest *newRequest = requestFromDelegate(initialRequest, identifier, error);
NSURLResponse *response = nil;
NSData *result = nil;
if (error == nil) {
ASSERT(newRequest != nil);
result = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
}
[initialRequest release];
if (error == nil)
getResourceResponse(r, response);
else {
r = ResourceResponse(URL, String(), 0, String(), String());
if ([error domain] == NSURLErrorDomain)
r.setHTTPStatusCode([error code]);
else
r.setHTTPStatusCode(404);
}
sendRemainingDelegateMessages(identifier, response, [result length], error);
data.resize([result length]);
memcpy(data.data(), [result bytes], [result length]);
}
Frame* FrameLoader::createFrame(const KURL& url, const String& name, Element* ownerElement, const String& referrer)
{
BOOL allowsScrolling = YES;
int marginWidth = -1;
int marginHeight = -1;
if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
HTMLFrameElement* o = static_cast<HTMLFrameElement*>(ownerElement);
allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff;
marginWidth = o->getMarginWidth();
marginHeight = o->getMarginHeight();
}
BEGIN_BLOCK_OBJC_EXCEPTIONS;
return [[Mac(m_frame)->bridge() createChildFrameNamed:name
withURL:url.getNSURL()
referrer:referrer
ownerElement:ownerElement
allowsScrolling:allowsScrolling
marginWidth:marginWidth
marginHeight:marginHeight] _frame];
END_BLOCK_OBJC_EXCEPTIONS;
return 0;
}
ObjectContentType FrameLoader::objectContentType(const KURL& url, const String& mimeType)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
return (ObjectContentType)[Mac(m_frame)->bridge() determineObjectFromMIMEType:mimeType URL:url.getNSURL()];
END_BLOCK_OBJC_EXCEPTIONS;
return ObjectContentNone;
}
static NSArray* nsArray(const Vector<String>& vector)
{
unsigned len = vector.size();
NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
for (unsigned x = 0; x < len; x++)
[array addObject:vector[x]];
return array;
}
Widget* FrameLoader::createPlugin(Element* element, const KURL& url,
const Vector<String>& paramNames, const Vector<String>& paramValues,
const String& mimeType)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
return new Widget([Mac(m_frame)->bridge() viewForPluginWithURL:url.getNSURL()
attributeNames:nsArray(paramNames)
attributeValues:nsArray(paramValues)
MIMEType:mimeType
DOMElement:[DOMElement _elementWith:element]
loadManually:m_frame->document()->isPluginDocument()]);
END_BLOCK_OBJC_EXCEPTIONS;
return 0;
}
void FrameLoader::redirectDataToPlugin(Widget* pluginWidget)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[Mac(m_frame)->bridge() redirectDataToPlugin:pluginWidget->getView()];
END_BLOCK_OBJC_EXCEPTIONS;
}
Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, Element* element, const HashMap<String, String>& args)
{
Widget* result = new Widget;
BEGIN_BLOCK_OBJC_EXCEPTIONS;
NSMutableArray *attributeNames = [[NSMutableArray alloc] init];
NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
DeprecatedString baseURLString;
HashMap<String, String>::const_iterator end = args.end();
for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) {
if (it->first.lower() == "baseurl")
baseURLString = it->second.deprecatedString();
[attributeNames addObject:it->first];
[attributeValues addObject:it->second];
}
if (baseURLString.isEmpty())
baseURLString = m_frame->document()->baseURL();
result->setView([Mac(m_frame)->bridge() viewForJavaAppletWithFrame:NSMakeRect(0, 0, size.width(), size.height())
attributeNames:attributeNames
attributeValues:attributeValues
baseURL:completeURL(baseURLString).getNSURL()
DOMElement:[DOMElement _elementWith:element]]);
[attributeNames release];
[attributeValues release];
m_frame->view()->addChild(result);
END_BLOCK_OBJC_EXCEPTIONS;
return result;
}
void FrameLoader::partClearedInBegin()
{
if (m_frame->javaScriptEnabled())
[Mac(m_frame)->bridge() windowObjectCleared];
}
void FrameLoader::saveDocumentState()
{
// Do not save doc state if the page has a password field and a form that would be submitted via https.
Document* document = m_frame->document();
if (!(document && document->hasPasswordField() && document->hasSecureForm())) {
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[Mac(m_frame)->bridge() saveDocumentState];
END_BLOCK_OBJC_EXCEPTIONS;
}
}
void FrameLoader::restoreDocumentState()
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[Mac(m_frame)->bridge() restoreDocumentState];
END_BLOCK_OBJC_EXCEPTIONS;
}
String FrameLoader::overrideMediaType() const
{
NSString *overrideType = [Mac(m_frame)->bridge() overrideMediaType];
if (overrideType)
return overrideType;
return String();
}
NSData *FrameLoader::mainResourceData() const
{
if (!m_mainResourceLoader)
return nil;
return m_mainResourceLoader->resourceData();
}
bool FrameLoader::canGoBackOrForward(int distance) const
{
return [Mac(m_frame)->bridge() canGoBackOrForward:distance];
}
KURL FrameLoader::originalRequestURL() const
{
return [activeDocumentLoader()->initialRequest() URL];
}
int FrameLoader::getHistoryLength()
{
return [Mac(m_frame)->bridge() historyLength];
}
void FrameLoader::goBackOrForward(int distance)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[Mac(m_frame)->bridge() goBackOrForward:distance];
END_BLOCK_OBJC_EXCEPTIONS;
}
KURL FrameLoader::historyURL(int distance)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
return [Mac(m_frame)->bridge() historyURL:distance];
END_BLOCK_OBJC_EXCEPTIONS;
return KURL();
}
void FrameLoader::didFinishLoad(ResourceLoader* loader)
{
m_client->completeProgress(loader->identifier());
m_client->dispatchDidFinishLoading(activeDocumentLoader(), loader->identifier());
}
PolicyCheck::PolicyCheck()
: m_navigationFunction(0)
, m_newWindowFunction(0)
, m_contentFunction(0)
{
}
void PolicyCheck::clear()
{
clearRequest();
m_navigationFunction = 0;
m_newWindowFunction = 0;
m_contentFunction = 0;
}
void PolicyCheck::set(NSURLRequest *request, PassRefPtr<FormState> formState,
NavigationPolicyDecisionFunction function, void* argument)
{
m_request = request;
m_formState = formState;
m_frameName = String();
m_navigationFunction = function;
m_newWindowFunction = 0;
m_contentFunction = 0;
m_argument = argument;
}
void PolicyCheck::set(NSURLRequest *request, PassRefPtr<FormState> formState,
const String& frameName, NewWindowPolicyDecisionFunction function, void* argument)
{
m_request = request;
m_formState = formState;
m_frameName = frameName;
m_navigationFunction = 0;
m_newWindowFunction = function;
m_contentFunction = 0;
m_argument = argument;
}
void PolicyCheck::set(ContentPolicyDecisionFunction function, void* argument)
{
m_request = nil;
m_formState = 0;
m_frameName = String();
m_navigationFunction = 0;
m_newWindowFunction = 0;
m_contentFunction = function;
m_argument = argument;
}
void PolicyCheck::call()
{
if (m_navigationFunction)
m_navigationFunction(m_argument, m_request.get(), m_formState.get());
if (m_newWindowFunction)
m_newWindowFunction(m_argument, m_request.get(), m_formState.get(), m_frameName);
ASSERT(!m_contentFunction);
}
void PolicyCheck::call(PolicyAction action)
{
ASSERT(!m_navigationFunction);
ASSERT(!m_newWindowFunction);
ASSERT(m_contentFunction);
m_contentFunction(m_argument, action);
}
void PolicyCheck::clearRequest()
{
m_request = nil;
m_formState = 0;
m_frameName = String();
}
}