Reviewed by Dave Harrison, Oliver, and Darin
[WebKit-https.git] / WebCore / loader / mac / FrameLoaderMac.mm
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer. 
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution. 
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "config.h"
30 #import "FrameLoader.h"
31
32 #import "BlockExceptions.h"
33 #import "Cache.h"
34 #import "Chrome.h"
35 #import "DOMElementInternal.h"
36 #import "Document.h"
37 #import "DocumentLoader.h"
38 #import "FloatRect.h"
39 #import "FormDataStreamMac.h"
40 #import "FormState.h"
41 #import "FrameLoadRequest.h"
42 #import "FrameLoaderClient.h"
43 #import "FrameMac.h"
44 #import "FramePrivate.h"
45 #import "FrameTree.h"
46 #import "FrameView.h"
47 #import "HTMLFormElement.h"
48 #import "HTMLFrameElement.h"
49 #import "HTMLNames.h"
50 #import "LoaderNSURLExtras.h"
51 #import "LoaderNSURLRequestExtras.h"
52 #import "MainResourceLoader.h"
53 #import "NavigationAction.h"
54 #import "Page.h"
55 #import "PageState.h"
56 #import "Plugin.h"
57 #import "ResourceResponse.h"
58 #import "ResourceResponseMac.h"
59 #import "SubresourceLoader.h"
60 #import "SystemTime.h"
61 #import "TextResourceDecoder.h"
62 #import "WebCoreFrameBridge.h"
63 #import "WebCoreIconDatabaseBridge.h"
64 #import "WebCorePageState.h"
65 #import "WebCoreSystemInterface.h"
66 #import "WebDataProtocol.h"
67 #import "Widget.h"
68 #import "WindowFeatures.h"
69 #import <kjs/JSLock.h>
70 #import <wtf/Assertions.h>
71
72 namespace WebCore {
73
74 using namespace HTMLNames;
75
76 void FrameLoader::load(const FrameLoadRequest& request, bool userGesture, Event* event,
77     Element* submitForm, const HashMap<String, String>& formValues)
78 {
79     String referrer;
80     String argsReferrer = request.resourceRequest().httpReferrer();
81     if (!argsReferrer.isEmpty())
82         referrer = argsReferrer;
83     else
84         referrer = m_outgoingReferrer;
85  
86     bool hideReferrer;
87     if (!canLoad(request.resourceRequest().url().getNSURL(), referrer, hideReferrer))
88         return;
89     if (hideReferrer)
90         referrer = String();
91     
92     Frame* targetFrame = m_frame->tree()->find(request.frameName());
93     if (!canTarget(targetFrame))
94         return;
95         
96     if (request.resourceRequest().httpMethod() != "POST") {
97         FrameLoadType loadType;
98         if (request.resourceRequest().cachePolicy() == ReloadIgnoringCacheData)
99             loadType = FrameLoadTypeReload;
100         else if (!userGesture)
101             loadType = FrameLoadTypeInternal;
102         else
103             loadType = FrameLoadTypeStandard;    
104     
105         load(request.resourceRequest().url(), referrer, loadType, 
106             request.frameName(), event, submitForm, formValues);
107     } else
108         post(request.resourceRequest().url(), referrer, request.frameName(), 
109             request.resourceRequest().httpBody(), request.resourceRequest().httpContentType(), event, submitForm, formValues);
110
111     if (targetFrame && targetFrame != m_frame)
112         targetFrame->page()->chrome()->focus();
113 }
114
115 void FrameLoader::load(const KURL& URL, const String& referrer, FrameLoadType newLoadType,
116     const String& frameName, Event* event, Element* form, const HashMap<String, String>& values)
117 {
118     bool isFormSubmission = !values.isEmpty();
119     
120     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL.getNSURL()];
121     setHTTPReferrer(request, referrer);
122     addExtraFieldsToRequest(request, true, event || isFormSubmission);
123     if (newLoadType == FrameLoadTypeReload)
124         [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
125
126     ASSERT(newLoadType != FrameLoadTypeSame);
127
128     NavigationAction action(URL, newLoadType, isFormSubmission, event);
129
130     RefPtr<FormState> formState;
131     if (form && !values.isEmpty())
132         formState = FormState::create(form, values, m_frame);
133     
134     if (!frameName.isEmpty()) {
135         if (Frame* targetFrame = m_frame->tree()->find(frameName))
136             targetFrame->loader()->load(URL, referrer, newLoadType, String(), event, form, values);
137         else
138             checkNewWindowPolicy(action, request, formState.release(), frameName);
139         [request release];
140         return;
141     }
142
143     RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
144
145     bool sameURL = m_client->shouldTreatURLAsSameAsCurrent(URL);
146     
147     // Make sure to do scroll to anchor processing even if the URL is
148     // exactly the same so pages with '#' links and DHTML side effects
149     // work properly.
150     if (!isFormSubmission
151         && newLoadType != FrameLoadTypeReload
152         && newLoadType != FrameLoadTypeSame
153         && !shouldReload(URL, url())
154         // We don't want to just scroll if a link from within a
155         // frameset is trying to reload the frameset into _top.
156         && !m_frame->isFrameSet()) {
157
158         // Just do anchor navigation within the existing content.
159         
160         // We don't do this if we are submitting a form, explicitly reloading,
161         // currently displaying a frameset, or if the new URL does not have a fragment.
162         // These rules are based on what KHTML was doing in KHTMLPart::openURL.
163         
164         // FIXME: What about load types other than Standard and Reload?
165         
166         oldDocumentLoader->setTriggeringAction(action);
167         stopPolicyCheck();
168         checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
169             callContinueFragmentScrollAfterNavigationPolicy, this);
170     } else {
171         // must grab this now, since this load may stop the previous load and clear this flag
172         bool isRedirect = m_quickRedirectComing;
173         load(request, action, newLoadType, formState.release());
174         if (isRedirect) {
175             m_quickRedirectComing = false;
176             if (m_provisionalDocumentLoader)
177                 m_provisionalDocumentLoader->setIsClientRedirect(true);
178         } else if (sameURL)
179             // Example of this case are sites that reload the same URL with a different cookie
180             // driving the generated content, or a master frame with links that drive a target
181             // frame, where the user has clicked on the same link repeatedly.
182             m_loadType = FrameLoadTypeSame;
183     }
184     
185     [request release];
186 }
187
188 void FrameLoader::load(NSURLRequest *request)
189 {
190     // FIXME: is this the right place to reset loadType? Perhaps this should be done after loading is finished or aborted.
191     m_loadType = FrameLoadTypeStandard;
192     load(m_client->createDocumentLoader(request).get());
193 }
194
195 void FrameLoader::load(NSURLRequest *request, const String& frameName)
196 {
197     if (frameName.isEmpty()) {
198         load(request);
199         return;
200     }
201
202     Frame* frame = m_frame->tree()->find(frameName);
203     if (frame) {
204         frame->loader()->load(request);
205         return;
206     }
207
208     checkNewWindowPolicy(NavigationAction([request URL], NavigationTypeOther),
209         request, 0, frameName);
210 }
211
212 void FrameLoader::load(NSURLRequest *request, const NavigationAction& action, FrameLoadType type, PassRefPtr<FormState> formState)
213 {
214     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request);
215     setPolicyDocumentLoader(loader.get());
216
217     loader->setTriggeringAction(action);
218     if (m_documentLoader)
219         loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
220
221     load(loader.get(), type, formState);
222 }
223
224 void FrameLoader::load(DocumentLoader* newDocumentLoader)
225 {
226     stopPolicyCheck();
227     setPolicyDocumentLoader(newDocumentLoader);
228
229     NSMutableURLRequest *r = newDocumentLoader->request();
230     addExtraFieldsToRequest(r, true, false);
231     FrameLoadType type;
232     if (m_client->shouldTreatURLAsSameAsCurrent([newDocumentLoader->originalRequest() URL])) {
233         [r setCachePolicy:NSURLRequestReloadIgnoringCacheData];
234         type = FrameLoadTypeSame;
235     } else
236         type = FrameLoadTypeStandard;
237
238     if (m_documentLoader)
239         newDocumentLoader->setOverrideEncoding(m_documentLoader->overrideEncoding());
240     
241     // When we loading alternate content for an unreachable URL that we're
242     // visiting in the b/f list, we treat it as a reload so the b/f list 
243     // is appropriately maintained.
244     if (shouldReloadToHandleUnreachableURL(newDocumentLoader->originalRequest())) {
245         ASSERT(type == FrameLoadTypeStandard);
246         type = FrameLoadTypeReload;
247     }
248
249     load(newDocumentLoader, type, 0);
250 }
251
252 void FrameLoader::load(DocumentLoader* loader, FrameLoadType type, PassRefPtr<FormState> formState)
253 {
254     ASSERT(m_client->hasWebView());
255
256     // Unfortunately the view must be non-nil, this is ultimately due
257     // to parser requiring a FrameView.  We should fix this dependency.
258
259     ASSERT(m_client->hasFrameView());
260
261     m_policyLoadType = type;
262
263     if (Frame* parent = m_frame->tree()->parent())
264         loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
265
266     stopPolicyCheck();
267     setPolicyDocumentLoader(loader);
268
269     checkNavigationPolicy(loader->request(), loader, formState,
270         callContinueLoadAfterNavigationPolicy, this);
271 }
272
273 bool FrameLoader::canLoad(NSURL *URL, const String& referrer, bool& hideReferrer)
274 {
275     bool referrerIsWebURL = referrer.startsWith("http:", false) || referrer.startsWith("https:", false);
276     bool referrerIsLocalURL = referrer.startsWith("file:", false) || referrer.startsWith("applewebdata:");
277     bool URLIsFileURL = [URL scheme] && [[URL scheme] compare:@"file" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
278     bool referrerIsSecureURL = referrer.startsWith("https:", false);
279     bool URLIsSecureURL = [URL scheme] && [[URL scheme] compare:@"https" options:(NSCaseInsensitiveSearch|NSLiteralSearch)] == NSOrderedSame;
280     
281     hideReferrer = !referrerIsWebURL || (referrerIsSecureURL && !URLIsSecureURL);
282     return !URLIsFileURL || referrerIsLocalURL;
283 }
284
285 bool FrameLoader::startLoadingMainResource(NSMutableURLRequest *request, id identifier)
286 {
287     ASSERT(!m_mainResourceLoader);
288     m_mainResourceLoader = MainResourceLoader::create(m_frame);
289     m_mainResourceLoader->setIdentifier(identifier);
290     addExtraFieldsToRequest(request, true, false);
291     if (!m_mainResourceLoader->load(request)) {
292         // FIXME: If this should really be caught, we should just ASSERT this doesn't happen;
293         // should it be caught by other parts of WebKit or other parts of the app?
294         LOG_ERROR("could not create WebResourceHandle for URL %@ -- should be caught by policy handler level", [request URL]);
295         m_mainResourceLoader = 0;
296         return false;
297     }
298     return true;
299 }
300
301 // FIXME: Poor method name; also, why is this not part of startProvisionalLoad:?
302 void FrameLoader::startLoading()
303 {
304     if (!m_provisionalDocumentLoader)
305         return;
306
307     m_provisionalDocumentLoader->prepareForLoadStart();
308
309     if (m_mainResourceLoader)
310         return;
311
312     m_client->clearLoadingFromPageCache(m_provisionalDocumentLoader.get());
313
314     id identifier = m_client->dispatchIdentifierForInitialRequest
315         (m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
316         
317     if (!startLoadingMainResource(m_provisionalDocumentLoader->actualRequest(), identifier))
318         m_provisionalDocumentLoader->updateLoading();
319 }
320
321 void FrameLoader::cancelMainResourceLoad(NSError *error)
322 {
323     m_mainResourceLoader->cancel(error);
324 }
325
326 id FrameLoader::identifierForInitialRequest(NSURLRequest *clientRequest)
327 {
328     return m_client->dispatchIdentifierForInitialRequest(activeDocumentLoader(), clientRequest);
329 }
330
331 void FrameLoader::applyUserAgent(NSMutableURLRequest *request)
332 {
333     static String lastUserAgent;
334     static RetainPtr<NSString> lastUserAgentNSString;
335
336     String userAgent = client()->userAgent();
337     ASSERT(!userAgent.isNull());
338     if (userAgent != lastUserAgent) {
339         lastUserAgent = userAgent;
340         lastUserAgentNSString = userAgent;
341     }
342
343     [request setValue:lastUserAgentNSString.get() forHTTPHeaderField:@"User-Agent"];
344 }
345
346 NSURLRequest *FrameLoader::willSendRequest(ResourceLoader* loader, NSMutableURLRequest *clientRequest, NSURLResponse *redirectResponse)
347 {
348     applyUserAgent(clientRequest);
349     return m_client->dispatchWillSendRequest(activeDocumentLoader(), loader->identifier(), clientRequest, redirectResponse);
350 }
351
352 void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, NSURLAuthenticationChallenge *currentWebChallenge)
353 {
354     m_client->dispatchDidReceiveAuthenticationChallenge(activeDocumentLoader(), loader->identifier(), currentWebChallenge);
355 }
356
357 void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, NSURLAuthenticationChallenge *currentWebChallenge)
358 {
359     m_client->dispatchDidCancelAuthenticationChallenge(activeDocumentLoader(), loader->identifier(), currentWebChallenge);
360 }
361
362 void FrameLoader::didReceiveResponse(ResourceLoader* loader, NSURLResponse *r)
363 {
364     activeDocumentLoader()->addResponse(r);
365     
366     m_client->incrementProgress(loader->identifier(), r);
367     m_client->dispatchDidReceiveResponse(activeDocumentLoader(), loader->identifier(), r);
368 }
369
370 void FrameLoader::didReceiveData(ResourceLoader* loader, NSData *data, int lengthReceived)
371 {
372     m_client->incrementProgress(loader->identifier(), data);
373     m_client->dispatchDidReceiveContentLength(activeDocumentLoader(), loader->identifier(), lengthReceived);
374 }
375
376 void FrameLoader::didFailToLoad(ResourceLoader* loader, NSError *error)
377 {
378     m_client->completeProgress(loader->identifier());
379     if (error)
380         m_client->dispatchDidFailLoading(activeDocumentLoader(), loader->identifier(), error);
381 }
382
383 NSURLRequest *FrameLoader::originalRequest() const
384 {
385     return activeDocumentLoader()->originalRequestCopy();
386 }
387
388 void FrameLoader::receivedMainResourceError(NSError *error, bool isComplete)
389 {
390     // Retain because the stop may release the last reference to it.
391     RefPtr<Frame> protect(m_frame);
392
393     RefPtr<DocumentLoader> loader = activeDocumentLoader();
394     
395     if (isComplete) {
396         // FIXME: Don't want to do this if an entirely new load is going, so should check
397         // that both data sources on the frame are either this or nil.
398         stop();
399         if (m_client->shouldFallBack(error))
400             handleFallbackContent();
401     }
402     
403     if (m_state == FrameStateProvisional) {
404         NSURL *failedURL = [m_provisionalDocumentLoader->originalRequestCopy() URL];
405         didNotOpenURL(failedURL);
406
407         // We might have made a page cache item, but now we're bailing out due to an error before we ever
408         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
409         // so that the existing view (that wenever got far enough to replace) can continue being used.
410         Document* document = m_frame->document();
411         if (document)
412             document->setInPageCache(false);
413         m_client->invalidateCurrentItemPageCache();
414         
415         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
416         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
417         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
418         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
419         // has ended.
420         if (m_sentRedirectNotification)
421             clientRedirectCancelledOrFinished(false);
422     }
423     
424     
425     loader->mainReceivedError(error, isComplete);
426 }
427
428 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
429     NSURLRequest *request, PassRefPtr<FormState>)
430 {
431     FrameLoader* loader = static_cast<FrameLoader*>(argument);
432     loader->continueFragmentScrollAfterNavigationPolicy(request);
433 }
434
435 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(NSURLRequest *request)
436 {
437     if (!request)
438         return;
439     
440     NSURL *URL = [request URL];
441     
442     bool isRedirect = m_quickRedirectComing;
443     m_quickRedirectComing = false;
444     
445     m_documentLoader->replaceRequestURLForAnchorScroll(URL);
446     if (!isRedirect && !m_client->shouldTreatURLAsSameAsCurrent(URL)) {
447         // NB: must happen after _setURL, since we add based on the current request.
448         // Must also happen before we openURL and displace the scroll position, since
449         // adding the BF item will save away scroll state.
450         
451         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
452         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
453         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
454         // though its load is not yet done.  I think this all works out OK, for one because
455         // we have already saved away the scroll and doc state for the long slow load,
456         // but it's not an obvious case.
457
458         m_client->addHistoryItemForFragmentScroll();
459     }
460     
461     scrollToAnchor(URL);
462     
463     if (!isRedirect)
464         // This will clear previousItem from the rest of the frame tree that didn't
465         // doing any loading. We need to make a pass on this now, since for anchor nav
466         // we'll not go through a real load and reach Completed state.
467         checkLoadComplete();
468  
469     m_client->dispatchDidChangeLocationWithinPage();
470     m_client->didFinishLoad();
471 }
472
473 void FrameLoader::opened()
474 {
475     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
476         m_client->updateHistoryAfterClientRedirect();
477
478     if (m_client->isLoadingFromPageCache(m_documentLoader.get())) {
479         // Force a layout to update view size and thereby update scrollbars.
480         m_client->forceLayout();
481
482         const ResponseVector& responses = m_documentLoader->responses();
483         size_t count = responses.size();
484         for (size_t i = 0; i < count; i++) {
485             NSURLResponse *response = responses[i].get();
486             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
487             NSError *error;
488             id identifier;
489             NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[response URL]];
490             requestFromDelegate(request, identifier, error);
491             sendRemainingDelegateMessages(identifier, response, (unsigned)[response expectedContentLength], error);
492             [request release];
493         }
494         
495         m_client->loadedFromPageCache();
496
497         m_documentLoader->setPrimaryLoadComplete(true);
498
499         // FIXME: Why only this frame and not parent frames?
500         checkLoadCompleteForThisFrame();
501     }
502 }
503
504 void FrameLoader::commitProvisionalLoad(NSDictionary *pageCache)
505 {
506     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
507     
508     if (m_loadType != FrameLoadTypeReplace)
509         closeOldDataSources();
510     
511     if (!pageCache)
512         m_client->makeRepresentation(pdl.get());
513     
514     transitionToCommitted(pageCache);
515     
516     // Call -_clientRedirectCancelledOrFinished: here so that the frame load delegate is notified that the redirect's
517     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
518     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
519     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
520     if (m_sentRedirectNotification)
521         clientRedirectCancelledOrFinished(false);
522     
523     WebCorePageState *pageState = [pageCache objectForKey:WebCorePageCacheStateKey];
524     if (PageState* frameState = [pageState impl]) {
525         open(*frameState);
526         frameState->clear();
527     } else {
528         NSURLResponse *response = pdl->response();
529     
530         NSURL *URL = [pdl->request() _webDataRequestBaseURL];
531         if (!URL)
532             URL = [response URL];
533         if (!URL || urlIsEmpty(URL))
534             URL = [NSURL URLWithString:@"about:blank"];    
535
536         m_responseMIMEType = [response MIMEType];
537         if (didOpenURL(URL)) {
538             if ([response isKindOfClass:[NSHTTPURLResponse class]])
539                 if (NSString *refresh = [[(NSHTTPURLResponse *)response allHeaderFields] objectForKey:@"Refresh"])
540                     m_responseRefreshHeader = refresh;
541             m_responseModifiedHeader = [wkGetNSURLResponseLastModifiedDate(response)
542                 descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
543         }
544     }
545     opened();
546 }
547
548 NSURLRequest *FrameLoader::initialRequest() const
549 {
550     return activeDocumentLoader()->initialRequest();
551 }
552
553 void FrameLoader::receivedData(NSData *data)
554 {
555     activeDocumentLoader()->receivedData(data);
556 }
557
558 void FrameLoader::setRequest(NSURLRequest *request)
559 {
560     activeDocumentLoader()->setRequest(request);
561 }
562
563 void FrameLoader::setResponse(NSURLResponse *response)
564 {
565     activeDocumentLoader()->setResponse(response);
566 }
567
568 void FrameLoader::mainReceivedError(NSError *error, bool isComplete)
569 {
570     activeDocumentLoader()->mainReceivedError(error, isComplete);
571 }
572
573 void FrameLoader::notifyIconChanged()
574 {
575     ASSERT([[WebCoreIconDatabaseBridge sharedInstance] _isEnabled]);
576     NSImage *icon = [[WebCoreIconDatabaseBridge sharedInstance]
577         iconForPageURL:urlOriginalDataAsString(activeDocumentLoader()->URL().getNSURL())
578         withSize:NSMakeSize(16, 16)];
579     m_client->dispatchDidReceiveIcon(icon);
580 }
581
582 NSError *FrameLoader::cancelledError(NSURLRequest *request) const
583 {
584     return m_client->cancelledError(request);
585 }
586
587 NSError *FrameLoader::fileDoesNotExistError(NSURLResponse *response) const
588 {
589     return m_client->fileDoesNotExistError(response);    
590 }
591
592 bool FrameLoader::willUseArchive(ResourceLoader* loader, NSURLRequest *request, NSURL *originalURL) const
593 {
594     return m_client->willUseArchive(loader, request, originalURL);
595 }
596
597 void FrameLoader::handleUnimplementablePolicy(NSError *error)
598 {
599     m_delegateIsHandlingUnimplementablePolicy = true;
600     m_client->dispatchUnableToImplementPolicy(error);
601     m_delegateIsHandlingUnimplementablePolicy = false;
602 }
603
604 void FrameLoader::cannotShowMIMEType(NSURLResponse *response)
605 {
606     handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
607 }
608
609 NSError *FrameLoader::interruptionForPolicyChangeError(NSURLRequest *request)
610 {
611     return m_client->interruptForPolicyChangeError(request);
612 }
613
614 void FrameLoader::checkNavigationPolicy(NSURLRequest *newRequest,
615     NavigationPolicyDecisionFunction function, void* argument)
616 {
617     checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
618 }
619
620 void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
621 {
622     m_policyCheck.set(function, argument);
623     m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
624         MIMEType, activeDocumentLoader()->request());
625 }
626
627 bool FrameLoader::shouldReloadToHandleUnreachableURL(NSURLRequest *request)
628 {
629     NSURL *unreachableURL = [request _webDataRequestUnreachableURL];
630     if (unreachableURL == nil)
631         return false;
632
633     if (!isBackForwardLoadType(m_policyLoadType))
634         return false;
635
636     // We only treat unreachableURLs specially during the delegate callbacks
637     // for provisional load errors and navigation policy decisions. The former
638     // case handles well-formed URLs that can't be loaded, and the latter
639     // case handles malformed URLs and unknown schemes. Loading alternate content
640     // at other times behaves like a standard load.
641     DocumentLoader* compareDocumentLoader = 0;
642     if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
643         compareDocumentLoader = m_policyDocumentLoader.get();
644     else if (m_delegateIsHandlingProvisionalLoadError)
645         compareDocumentLoader = m_provisionalDocumentLoader.get();
646
647     return compareDocumentLoader && [unreachableURL isEqual:[compareDocumentLoader->request() URL]];
648 }
649
650 void FrameLoader::reloadAllowingStaleData(const String& encoding)
651 {
652     if (!m_documentLoader)
653         return;
654
655     NSMutableURLRequest *request = [m_documentLoader->request() mutableCopy];
656     KURL unreachableURL = m_documentLoader->unreachableURL();
657     if (!unreachableURL.isEmpty())
658         [request setURL:unreachableURL.getNSURL()];
659
660     [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
661
662     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request);
663     setPolicyDocumentLoader(loader.get());
664
665     [request release];
666
667     loader->setOverrideEncoding(encoding);
668
669     load(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
670 }
671
672 void FrameLoader::reload()
673 {
674     if (!m_documentLoader)
675         return;
676
677     NSMutableURLRequest *initialRequest = m_documentLoader->request();
678     
679     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
680     // Reloading in this case will lose the current contents (see 4151001).
681     if ([[[initialRequest URL] absoluteString] length] == 0)
682         return;
683
684     // Replace error-page URL with the URL we were trying to reach.
685     NSURL *unreachableURL = [initialRequest _webDataRequestUnreachableURL];
686     if (unreachableURL != nil)
687         initialRequest = [NSURLRequest requestWithURL:unreachableURL];
688     
689     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest);
690     setPolicyDocumentLoader(loader.get());
691
692     NSMutableURLRequest *request = loader->request();
693
694     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
695
696     // If we're about to re-post, set up action so the application can warn the user.
697     if ([[request HTTPMethod] isEqualToString:@"POST"])
698         loader->setTriggeringAction(NavigationAction([request URL], NavigationTypeFormResubmitted));
699
700     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
701     
702     load(loader.get(), FrameLoadTypeReload, 0);
703 }
704
705 void FrameLoader::committedLoad(DocumentLoader* loader, NSData *data)
706 {
707     m_client->committedLoad(loader, data);
708 }
709
710 void FrameLoader::setMainDocumentError(DocumentLoader* loader, NSError *error)
711 {
712     m_client->setMainDocumentError(loader, error);
713 }
714
715 void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, NSError *error)
716 {
717     loader->setPrimaryLoadComplete(true);
718     m_client->dispatchDidLoadMainResource(activeDocumentLoader());
719     checkLoadComplete();
720 }
721
722 void FrameLoader::didChangeTitle(DocumentLoader* loader)
723 {
724     m_client->didChangeTitle(loader);
725
726     // The title doesn't get communicated to the WebView until we are committed.
727     if (loader->isCommitted())
728         if (NSURL *URLForHistory = canonicalURL(loader->URLForHistory().getNSURL())) {
729             // Must update the entries in the back-forward list too.
730             // This must go through the WebFrame because it has the right notion of the current b/f item.
731             m_client->setTitle(loader->title(), URLForHistory);
732             m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
733             m_client->dispatchDidReceiveTitle(loader->title());
734         }
735 }
736
737 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, NSURLRequest *request,
738     PassRefPtr<FormState> formState, const String& frameName)
739 {
740     m_policyCheck.set(request, formState, frameName,
741         callContinueLoadAfterNewWindowPolicy, this);
742     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
743         action, request, frameName);
744 }
745
746 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
747 {
748     PolicyCheck check = m_policyCheck;
749     m_policyCheck.clear();
750
751     switch (policy) {
752         case PolicyIgnore:
753             check.clearRequest();
754             break;
755         case PolicyDownload:
756             m_client->startDownload(check.request());
757             check.clearRequest();
758             break;
759         case PolicyUse:
760             break;
761     }
762
763     check.call();
764 }
765
766 void FrameLoader::checkNavigationPolicy(NSURLRequest *request, DocumentLoader* loader,
767     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
768 {
769     NavigationAction action = loader->triggeringAction();
770     if (action.isEmpty()) {
771         action = NavigationAction([request URL], NavigationTypeOther);
772         loader->setTriggeringAction(action);
773     }
774         
775     // Don't ask more than once for the same request or if we are loading an empty URL.
776     // This avoids confusion on the part of the client.
777     if ([request isEqual:loader->lastCheckedRequest()] || urlIsEmpty([request URL])) {
778         function(argument, request, 0);
779         return;
780     }
781     
782     // We are always willing to show alternate content for unreachable URLs;
783     // treat it like a reload so it maintains the right state for b/f list.
784     if ([request _webDataRequestUnreachableURL] != nil) {
785         if (isBackForwardLoadType(m_policyLoadType))
786             m_policyLoadType = FrameLoadTypeReload;
787         function(argument, request, 0);
788         return;
789     }
790     
791     loader->setLastCheckedRequest(request);
792
793     m_policyCheck.set(request, formState, function, argument);
794
795     m_delegateIsDecidingNavigationPolicy = true;
796     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
797         action, request);
798     m_delegateIsDecidingNavigationPolicy = false;
799 }
800
801 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
802 {
803     PolicyCheck check = m_policyCheck;
804     m_policyCheck.clear();
805
806     switch (policy) {
807         case PolicyIgnore:
808             check.clearRequest();
809             break;
810         case PolicyDownload:
811             m_client->startDownload(check.request());
812             check.clearRequest();
813             break;
814         case PolicyUse:
815             if (!m_client->canHandleRequest(check.request())) {
816                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
817                 check.clearRequest();
818             }
819             break;
820     }
821
822     check.call();
823 }
824
825 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
826     NSURLRequest *request, PassRefPtr<FormState> formState)
827 {
828     FrameLoader* loader = static_cast<FrameLoader*>(argument);
829     loader->continueLoadAfterNavigationPolicy(request, formState);
830 }
831
832 void FrameLoader::continueLoadAfterNavigationPolicy(NSURLRequest *request,
833     PassRefPtr<FormState> formState)
834 {
835     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
836     // nil policyDataSource because loading the alternate page will have passed
837     // through this method already, nested; otherwise, policyDataSource should still be set.
838     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
839
840     BOOL isTargetItem = m_client->provisionalItemIsTarget();
841
842     // Two reasons we can't continue:
843     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
844     //       is the user responding Cancel to the form repost nag sheet.
845     //    2) User responded Cancel to an alert popped up by the before unload event handler.
846     // The "before unload" event handler runs only for the main frame.
847     bool canContinue = request && (!isLoadingMainFrame() || Mac(m_frame)->shouldClose());
848
849     if (!canContinue) {
850         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
851         // need to report that the client redirect was cancelled.
852         if (m_quickRedirectComing)
853             clientRedirectCancelledOrFinished(false);
854
855         setPolicyDocumentLoader(0);
856
857         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
858         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
859         // we only do this when punting a navigation for the target frame or top-level frame.  
860         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
861             m_client->resetBackForwardList();
862
863         return;
864     }
865
866     FrameLoadType type = m_policyLoadType;
867     stopAllLoaders();
868     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
869     m_loadType = type;
870     setState(FrameStateProvisional);
871
872     setPolicyDocumentLoader(0);
873
874     if (isBackForwardLoadType(type) && m_client->loadProvisionalItemFromPageCache())
875         return;
876
877     if (formState)
878         m_client->dispatchWillSubmitForm(&FrameLoader::continueAfterWillSubmitForm, formState);
879     else
880         continueAfterWillSubmitForm();
881 }
882
883 void FrameLoader::transitionToCommitted(NSDictionary *pageCache)
884 {
885     ASSERT(m_client->hasWebView());
886     ASSERT(m_state == FrameStateProvisional);
887
888     if (m_state != FrameStateProvisional)
889         return;
890
891     m_client->setCopiesOnScroll();
892     m_client->updateHistoryForCommit();
893
894     // The call to closeURL invokes the unload event handler, which can execute arbitrary
895     // JavaScript. If the script initiates a new load, we need to abandon the current load,
896     // or the two will stomp each other.
897     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
898     closeDocument();
899     if (pdl != m_provisionalDocumentLoader)
900         return;
901
902     commitProvisionalLoad();
903
904     // Handle adding the URL to the back/forward list.
905     DocumentLoader* dl = m_documentLoader.get();
906     String ptitle = dl->title();
907
908     switch (m_loadType) {
909     case FrameLoadTypeForward:
910     case FrameLoadTypeBack:
911     case FrameLoadTypeIndexedBackForward:
912         if (m_client->hasBackForwardList()) {
913             m_client->updateHistoryForBackForwardNavigation();
914
915             // Create a document view for this document, or used the cached view.
916             if (pageCache)
917                 m_client->setDocumentViewFromPageCache(pageCache);
918             else
919                 m_client->makeDocumentView();
920         }
921         break;
922
923     case FrameLoadTypeReload:
924     case FrameLoadTypeSame:
925     case FrameLoadTypeReplace:
926         m_client->updateHistoryForReload();
927         m_client->makeDocumentView();
928         break;
929
930     // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
931     case FrameLoadTypeReloadAllowingStaleData:
932         m_client->makeDocumentView();
933         break;
934
935     case FrameLoadTypeStandard:
936         m_client->updateHistoryForStandardLoad();
937         m_client->makeDocumentView();
938         break;
939
940     case FrameLoadTypeInternal:
941         m_client->updateHistoryForInternalLoad();
942         m_client->makeDocumentView();
943         break;
944
945     // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
946     // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
947     default:
948         ASSERT_NOT_REACHED();
949     }
950
951     // Tell the client we've committed this URL.
952     ASSERT(m_client->hasFrameView());
953     m_client->dispatchDidCommitLoad();
954     
955     // If we have a title let the WebView know about it.
956     if (!ptitle.isNull())
957         m_client->dispatchDidReceiveTitle(ptitle);
958 }
959
960 void FrameLoader::checkLoadCompleteForThisFrame()
961 {
962     ASSERT(m_client->hasWebView());
963
964     switch (m_state) {
965         case FrameStateProvisional: {
966             if (m_delegateIsHandlingProvisionalLoadError)
967                 return;
968
969             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
970             if (!pdl)
971                 return;
972                 
973             // If we've received any errors we may be stuck in the provisional state and actually complete.
974             NSError *error = pdl->mainDocumentError();
975             if (!error)
976                 return;
977
978             // Check all children first.
979             LoadErrorResetToken *resetToken = m_client->tokenForLoadErrorReset();
980             bool shouldReset = true;
981             if (!pdl->isLoadingInAPISense()) {
982                 m_delegateIsHandlingProvisionalLoadError = true;
983                 m_client->dispatchDidFailProvisionalLoad(error);
984                 m_delegateIsHandlingProvisionalLoadError = false;
985
986                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
987                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
988                 // stopAllLoaders instead of stopLoadingSubframes?
989                 stopLoadingSubframes();
990                 pdl->stopLoading();
991
992                 // Finish resetting the load state, but only if another load hasn't been started by the
993                 // delegate callback.
994                 if (pdl == m_provisionalDocumentLoader)
995                     clearProvisionalLoad();
996                 else if (m_documentLoader) {
997                     KURL unreachableURL = m_documentLoader->unreachableURL();
998                     if (!unreachableURL.isEmpty() && unreachableURL == [pdl->request() URL])
999                         shouldReset = false;
1000                 }
1001             }
1002             if (shouldReset)
1003                 m_client->resetAfterLoadError(resetToken);
1004             else
1005                 m_client->doNotResetAfterLoadError(resetToken);
1006             return;
1007         }
1008         
1009         case FrameStateCommittedPage: {
1010             DocumentLoader* dl = m_documentLoader.get();            
1011             if (dl->isLoadingInAPISense())
1012                 return;
1013
1014             markLoadComplete();
1015
1016             // FIXME: Is this subsequent work important if we already navigated away?
1017             // Maybe there are bugs because of that, or extra work we can skip because
1018             // the new page is ready.
1019
1020             m_client->forceLayoutForNonHTML();
1021              
1022             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
1023             if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload)
1024                     && m_client->hasBackForwardList())
1025                 m_client->restoreScrollPositionAndViewState();
1026
1027             NSError *error = dl->mainDocumentError();
1028             if (error)
1029                 m_client->dispatchDidFailLoad(error);
1030             else
1031                 m_client->dispatchDidFinishLoad();
1032
1033             m_client->progressCompleted();
1034             return;
1035         }
1036         
1037         case FrameStateComplete:
1038             // Even if already complete, we might have set a previous item on a frame that
1039             // didn't do any data loading on the past transaction. Make sure to clear these out.
1040             m_client->frameLoadCompleted();
1041             return;
1042     }
1043
1044     ASSERT_NOT_REACHED();
1045 }
1046
1047 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
1048     NSURLRequest *request, PassRefPtr<FormState> formState, const String& frameName)
1049 {
1050     FrameLoader* loader = static_cast<FrameLoader*>(argument);
1051     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName);
1052 }
1053
1054 void FrameLoader::continueLoadAfterNewWindowPolicy(NSURLRequest *request,
1055     PassRefPtr<FormState> formState, const String& frameName)
1056 {
1057     if (!request)
1058         return;
1059
1060     RefPtr<Frame> frame = m_frame;
1061     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(nil);
1062     if (!mainFrame)
1063         return;
1064
1065     mainFrame->tree()->setName(frameName);
1066     mainFrame->loader()->m_client->dispatchShow();
1067     mainFrame->loader()->setOpener(frame.get());
1068     mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
1069 }
1070
1071 void FrameLoader::sendRemainingDelegateMessages(id identifier, NSURLResponse *response, unsigned length, NSError *error)
1072 {    
1073     if (response)
1074         m_client->dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
1075     
1076     if (length > 0)
1077         m_client->dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
1078     
1079     if (!error)
1080         m_client->dispatchDidFinishLoading(m_documentLoader.get(), identifier);
1081     else
1082         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
1083 }
1084
1085 NSURLRequest *FrameLoader::requestFromDelegate(NSURLRequest *request, id& identifier, NSError *& error)
1086 {
1087     ASSERT(request != nil);
1088
1089     identifier = m_client->dispatchIdentifierForInitialRequest(m_documentLoader.get(), request); 
1090     NSURLRequest *newRequest = m_client->dispatchWillSendRequest(m_documentLoader.get(), identifier, request, nil);
1091
1092     if (newRequest == nil)
1093         error = m_client->cancelledError(request);
1094     else
1095         error = nil;
1096
1097     return newRequest;
1098 }
1099
1100 void FrameLoader::loadedResourceFromMemoryCache(NSURLRequest *request, NSURLResponse *response, int length)
1101 {
1102     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
1103         return;
1104
1105     id identifier;
1106     NSError *error;
1107     requestFromDelegate(request, identifier, error);
1108     sendRemainingDelegateMessages(identifier, response, length, error);
1109 }
1110
1111 void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, const FormData& formData, 
1112     const String& contentType, Event* event, Element* form, const HashMap<String, String>& formValues)
1113 {
1114     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
1115     // This prevents a potential bug which may cause a page with a form that uses itself
1116     // as an action to be returned from the cache without submitting.
1117
1118     // FIXME: Where's the code that implements what the comment above says?
1119
1120     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL.getNSURL()];
1121     addExtraFieldsToRequest(request, true, true);
1122
1123     setHTTPReferrer(request, referrer);
1124     [request setHTTPMethod:@"POST"];
1125     setHTTPBody(request, formData);
1126     [request setValue:contentType forHTTPHeaderField:@"Content-Type"];
1127
1128     NavigationAction action(URL, FrameLoadTypeStandard, true, event);
1129
1130     RefPtr<FormState> formState;
1131     if (form && !formValues.isEmpty())
1132         formState = FormState::create(form, formValues, m_frame);
1133
1134     if (!frameName.isEmpty()) {
1135         if (Frame* targetFrame = m_frame->tree()->find(frameName))
1136             targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
1137         else
1138             checkNewWindowPolicy(action, request, formState.release(), frameName);
1139     } else
1140         load(request, action, FrameLoadTypeStandard, formState.release());
1141
1142     [request release];
1143 }
1144
1145 void FrameLoader::detachFromParent()
1146 {
1147     RefPtr<Frame> protect(m_frame);
1148
1149     closeDocument();
1150     stopAllLoaders();
1151     m_client->detachedFromParent1();
1152     detachChildren();
1153     m_client->detachedFromParent2();
1154     setDocumentLoader(0);
1155     m_client->detachedFromParent3();
1156     if (Frame* parent = m_frame->tree()->parent())
1157         parent->tree()->removeChild(m_frame);
1158     m_frame->setView(0);
1159     [Mac(m_frame)->bridge() close];
1160     m_client->detachedFromParent4();
1161 }
1162
1163 void FrameLoader::addExtraFieldsToRequest(NSMutableURLRequest *request, bool mainResource, bool alwaysFromRequest)
1164 {
1165     applyUserAgent(request);
1166     
1167     if (m_loadType == FrameLoadTypeReload)
1168         [request setValue:@"max-age=0" forHTTPHeaderField:@"Cache-Control"];
1169     
1170     // Don't set the cookie policy URL if it's already been set.
1171     if (![request mainDocumentURL]) {
1172         if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
1173             [request setMainDocumentURL:[request URL]];
1174         else
1175             [request setMainDocumentURL:m_frame->page()->mainFrame()->loader()->url().getNSURL()];
1176     }
1177     
1178     if (mainResource)
1179         [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"];
1180 }
1181
1182 bool FrameLoader::isReloading() const
1183 {
1184     return [documentLoader()->request() cachePolicy] == NSURLRequestReloadIgnoringCacheData;
1185 }
1186
1187 String FrameLoader::referrer() const
1188 {
1189     return [documentLoader()->request() valueForHTTPHeaderField:@"Referer"];
1190 }
1191
1192 void FrameLoader::loadEmptyDocumentSynchronously()
1193 {
1194     NSURL *url = [[NSURL alloc] initWithString:@""];
1195     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
1196     load(request);
1197     [request release];
1198     [url release];
1199 }
1200
1201 void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, Vector<char>& data, ResourceResponse& r)
1202 {
1203     NSURL *URL = request.url().getNSURL();
1204
1205     // Since this is a subresource, we can load any URL (we ignore the return value).
1206     // But we still want to know whether we should hide the referrer or not, so we call the canLoadURL method.
1207     String referrer = m_outgoingReferrer;
1208     bool hideReferrer;
1209     canLoad(URL, referrer, hideReferrer);
1210     if (hideReferrer)
1211         referrer = String();
1212     
1213     NSMutableURLRequest *initialRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
1214     [initialRequest setTimeoutInterval:10];
1215     
1216     [initialRequest setHTTPMethod:request.httpMethod()];
1217     
1218     if (!request.httpBody().isEmpty())        
1219         setHTTPBody(initialRequest, request.httpBody());
1220     
1221     HTTPHeaderMap::const_iterator end = request.httpHeaderFields().end();
1222     for (HTTPHeaderMap::const_iterator it = request.httpHeaderFields().begin(); it != end; ++it)
1223         [initialRequest addValue:it->second forHTTPHeaderField:it->first];
1224     
1225     if (isConditionalRequest(initialRequest))
1226         [initialRequest setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1227     else
1228         [initialRequest setCachePolicy:[documentLoader()->request() cachePolicy]];
1229     
1230     if (!referrer.isEmpty())
1231         setHTTPReferrer(initialRequest, referrer);
1232     
1233     [initialRequest setMainDocumentURL:[m_frame->page()->mainFrame()->loader()->documentLoader()->request() URL]];
1234     applyUserAgent(initialRequest);
1235     
1236     NSError *error = nil;
1237     id identifier = nil;    
1238     NSURLRequest *newRequest = requestFromDelegate(initialRequest, identifier, error);
1239     
1240     NSURLResponse *response = nil;
1241     NSData *result = nil;
1242     if (error == nil) {
1243         ASSERT(newRequest != nil);
1244         result = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
1245     }
1246     
1247     [initialRequest release];
1248
1249     if (error == nil)
1250         getResourceResponse(r, response);
1251     else {
1252         r = ResourceResponse(URL, String(), 0, String(), String());
1253         if ([error domain] == NSURLErrorDomain)
1254             r.setHTTPStatusCode([error code]);
1255         else
1256             r.setHTTPStatusCode(404);
1257     }
1258     
1259     sendRemainingDelegateMessages(identifier, response, [result length], error);
1260     
1261     data.resize([result length]);
1262     memcpy(data.data(), [result bytes], [result length]);
1263 }
1264
1265 Frame* FrameLoader::createFrame(const KURL& url, const String& name, Element* ownerElement, const String& referrer)
1266 {
1267     BOOL allowsScrolling = YES;
1268     int marginWidth = -1;
1269     int marginHeight = -1;
1270     if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
1271         HTMLFrameElement* o = static_cast<HTMLFrameElement*>(ownerElement);
1272         allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff;
1273         marginWidth = o->getMarginWidth();
1274         marginHeight = o->getMarginHeight();
1275     }
1276
1277     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1278     
1279     return [[Mac(m_frame)->bridge() createChildFrameNamed:name
1280                                                              withURL:url.getNSURL()
1281                                                             referrer:referrer 
1282                                                           ownerElement:ownerElement
1283                                                      allowsScrolling:allowsScrolling
1284                                                          marginWidth:marginWidth
1285                                                         marginHeight:marginHeight] _frame];
1286
1287     END_BLOCK_OBJC_EXCEPTIONS;
1288     return 0;
1289 }
1290
1291 ObjectContentType FrameLoader::objectContentType(const KURL& url, const String& mimeType)
1292 {
1293     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1294     return (ObjectContentType)[Mac(m_frame)->bridge() determineObjectFromMIMEType:mimeType URL:url.getNSURL()];
1295     END_BLOCK_OBJC_EXCEPTIONS;
1296     return ObjectContentNone;
1297 }
1298
1299 static NSArray* nsArray(const Vector<String>& vector)
1300 {
1301     unsigned len = vector.size();
1302     NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1303     for (unsigned x = 0; x < len; x++)
1304         [array addObject:vector[x]];
1305     return array;
1306 }
1307
1308 Widget* FrameLoader::createPlugin(Element* element, const KURL& url,
1309     const Vector<String>& paramNames, const Vector<String>& paramValues,
1310     const String& mimeType)
1311 {
1312     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1313     return new Widget([Mac(m_frame)->bridge() viewForPluginWithURL:url.getNSURL()
1314                                   attributeNames:nsArray(paramNames)
1315                                   attributeValues:nsArray(paramValues)
1316                                   MIMEType:mimeType
1317                                   DOMElement:[DOMElement _elementWith:element]
1318                                 loadManually:m_frame->document()->isPluginDocument()]);
1319     END_BLOCK_OBJC_EXCEPTIONS;
1320     return 0;
1321 }
1322
1323 void FrameLoader::redirectDataToPlugin(Widget* pluginWidget)
1324 {
1325     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1326     [Mac(m_frame)->bridge() redirectDataToPlugin:pluginWidget->getView()];
1327     END_BLOCK_OBJC_EXCEPTIONS;
1328 }
1329
1330 Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, Element* element, const HashMap<String, String>& args)
1331 {
1332     Widget* result = new Widget;
1333     
1334     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1335     
1336     NSMutableArray *attributeNames = [[NSMutableArray alloc] init];
1337     NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
1338     
1339     DeprecatedString baseURLString;
1340     HashMap<String, String>::const_iterator end = args.end();
1341     for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) {
1342         if (it->first.lower() == "baseurl")
1343             baseURLString = it->second.deprecatedString();
1344         [attributeNames addObject:it->first];
1345         [attributeValues addObject:it->second];
1346     }
1347     
1348     if (baseURLString.isEmpty())
1349         baseURLString = m_frame->document()->baseURL();
1350
1351     result->setView([Mac(m_frame)->bridge() viewForJavaAppletWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1352                                          attributeNames:attributeNames
1353                                         attributeValues:attributeValues
1354                                                 baseURL:completeURL(baseURLString).getNSURL()
1355                                              DOMElement:[DOMElement _elementWith:element]]);
1356     [attributeNames release];
1357     [attributeValues release];
1358     m_frame->view()->addChild(result);
1359     
1360     END_BLOCK_OBJC_EXCEPTIONS;
1361     
1362     return result;
1363 }
1364
1365 void FrameLoader::partClearedInBegin()
1366 {
1367     if (m_frame->javaScriptEnabled())
1368         [Mac(m_frame)->bridge() windowObjectCleared];
1369 }
1370
1371 void FrameLoader::saveDocumentState()
1372 {
1373     // Do not save doc state if the page has a password field and a form that would be submitted via https.
1374     Document* document = m_frame->document();
1375     if (!(document && document->hasPasswordField() && document->hasSecureForm())) {
1376         BEGIN_BLOCK_OBJC_EXCEPTIONS;
1377         [Mac(m_frame)->bridge() saveDocumentState];
1378         END_BLOCK_OBJC_EXCEPTIONS;
1379     }
1380 }
1381
1382 void FrameLoader::restoreDocumentState()
1383 {
1384     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1385     [Mac(m_frame)->bridge() restoreDocumentState];
1386     END_BLOCK_OBJC_EXCEPTIONS;
1387 }
1388
1389 String FrameLoader::overrideMediaType() const
1390 {
1391     NSString *overrideType = [Mac(m_frame)->bridge() overrideMediaType];
1392     if (overrideType)
1393         return overrideType;
1394     return String();
1395 }
1396
1397 NSData *FrameLoader::mainResourceData() const
1398 {
1399     if (!m_mainResourceLoader)
1400         return nil;
1401     return m_mainResourceLoader->resourceData();
1402 }
1403
1404 bool FrameLoader::canGoBackOrForward(int distance) const
1405 {
1406     return [Mac(m_frame)->bridge() canGoBackOrForward:distance];
1407 }
1408
1409 KURL FrameLoader::originalRequestURL() const
1410 {
1411     return [activeDocumentLoader()->initialRequest() URL];
1412 }
1413
1414 int FrameLoader::getHistoryLength()
1415 {
1416     return [Mac(m_frame)->bridge() historyLength];
1417 }
1418
1419 void FrameLoader::goBackOrForward(int distance)
1420 {
1421     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1422     [Mac(m_frame)->bridge() goBackOrForward:distance];
1423     END_BLOCK_OBJC_EXCEPTIONS;
1424 }
1425
1426 KURL FrameLoader::historyURL(int distance)
1427 {
1428     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1429     return [Mac(m_frame)->bridge() historyURL:distance];
1430     END_BLOCK_OBJC_EXCEPTIONS;
1431     return KURL();
1432 }
1433
1434 void FrameLoader::didFinishLoad(ResourceLoader* loader)
1435 {    
1436     m_client->completeProgress(loader->identifier());
1437     m_client->dispatchDidFinishLoading(activeDocumentLoader(), loader->identifier());
1438 }
1439
1440 PolicyCheck::PolicyCheck()
1441     : m_navigationFunction(0)
1442     , m_newWindowFunction(0)
1443     , m_contentFunction(0)
1444 {
1445 }
1446
1447 void PolicyCheck::clear()
1448 {
1449     clearRequest();
1450     m_navigationFunction = 0;
1451     m_newWindowFunction = 0;
1452     m_contentFunction = 0;
1453 }
1454
1455 void PolicyCheck::set(NSURLRequest *request, PassRefPtr<FormState> formState,
1456     NavigationPolicyDecisionFunction function, void* argument)
1457 {
1458     m_request = request;
1459     m_formState = formState;
1460     m_frameName = String();
1461
1462     m_navigationFunction = function;
1463     m_newWindowFunction = 0;
1464     m_contentFunction = 0;
1465     m_argument = argument;
1466 }
1467
1468 void PolicyCheck::set(NSURLRequest *request, PassRefPtr<FormState> formState,
1469     const String& frameName, NewWindowPolicyDecisionFunction function, void* argument)
1470 {
1471     m_request = request;
1472     m_formState = formState;
1473     m_frameName = frameName;
1474
1475     m_navigationFunction = 0;
1476     m_newWindowFunction = function;
1477     m_contentFunction = 0;
1478     m_argument = argument;
1479 }
1480
1481 void PolicyCheck::set(ContentPolicyDecisionFunction function, void* argument)
1482 {
1483     m_request = nil;
1484     m_formState = 0;
1485     m_frameName = String();
1486
1487     m_navigationFunction = 0;
1488     m_newWindowFunction = 0;
1489     m_contentFunction = function;
1490     m_argument = argument;
1491 }
1492
1493 void PolicyCheck::call()
1494 {
1495     if (m_navigationFunction)
1496         m_navigationFunction(m_argument, m_request.get(), m_formState.get());
1497     if (m_newWindowFunction)
1498         m_newWindowFunction(m_argument, m_request.get(), m_formState.get(), m_frameName);
1499     ASSERT(!m_contentFunction);
1500 }
1501
1502 void PolicyCheck::call(PolicyAction action)
1503 {
1504     ASSERT(!m_navigationFunction);
1505     ASSERT(!m_newWindowFunction);
1506     ASSERT(m_contentFunction);
1507     m_contentFunction(m_argument, action);
1508 }
1509
1510 void PolicyCheck::clearRequest()
1511 {
1512     m_request = nil;
1513     m_formState = 0;
1514     m_frameName = String();
1515 }
1516
1517 }