20123f4a4e4b697675c8fd7a4f68f0fce9196f33
[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     m_provisionalDocumentLoader->prepareForLoadStart();
305
306     if (m_mainResourceLoader)
307         return;
308
309     m_client->clearLoadingFromPageCache(m_provisionalDocumentLoader.get());
310
311     id identifier = m_client->dispatchIdentifierForInitialRequest
312         (m_provisionalDocumentLoader.get(), m_provisionalDocumentLoader->originalRequest());
313         
314     if (!startLoadingMainResource(m_provisionalDocumentLoader->actualRequest(), identifier))
315         m_provisionalDocumentLoader->updateLoading();
316 }
317
318 void FrameLoader::cancelMainResourceLoad(NSError *error)
319 {
320     m_mainResourceLoader->cancel(error);
321 }
322
323 id FrameLoader::identifierForInitialRequest(NSURLRequest *clientRequest)
324 {
325     return m_client->dispatchIdentifierForInitialRequest(activeDocumentLoader(), clientRequest);
326 }
327
328 void FrameLoader::applyUserAgent(NSMutableURLRequest *request)
329 {
330     static String lastUserAgent;
331     static RetainPtr<NSString> lastUserAgentNSString;
332
333     String userAgent = client()->userAgent();
334     ASSERT(!userAgent.isNull());
335     if (userAgent != lastUserAgent) {
336         lastUserAgent = userAgent;
337         lastUserAgentNSString = userAgent;
338     }
339
340     [request setValue:lastUserAgentNSString.get() forHTTPHeaderField:@"User-Agent"];
341 }
342
343 NSURLRequest *FrameLoader::willSendRequest(ResourceLoader* loader, NSMutableURLRequest *clientRequest, NSURLResponse *redirectResponse)
344 {
345     applyUserAgent(clientRequest);
346     return m_client->dispatchWillSendRequest(activeDocumentLoader(), loader->identifier(), clientRequest, redirectResponse);
347 }
348
349 void FrameLoader::didReceiveAuthenticationChallenge(ResourceLoader* loader, NSURLAuthenticationChallenge *currentWebChallenge)
350 {
351     m_client->dispatchDidReceiveAuthenticationChallenge(activeDocumentLoader(), loader->identifier(), currentWebChallenge);
352 }
353
354 void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, NSURLAuthenticationChallenge *currentWebChallenge)
355 {
356     m_client->dispatchDidCancelAuthenticationChallenge(activeDocumentLoader(), loader->identifier(), currentWebChallenge);
357 }
358
359 void FrameLoader::didReceiveResponse(ResourceLoader* loader, NSURLResponse *r)
360 {
361     activeDocumentLoader()->addResponse(r);
362     
363     m_client->incrementProgress(loader->identifier(), r);
364     m_client->dispatchDidReceiveResponse(activeDocumentLoader(), loader->identifier(), r);
365 }
366
367 void FrameLoader::didReceiveData(ResourceLoader* loader, NSData *data, int lengthReceived)
368 {
369     m_client->incrementProgress(loader->identifier(), data);
370     m_client->dispatchDidReceiveContentLength(activeDocumentLoader(), loader->identifier(), lengthReceived);
371 }
372
373 void FrameLoader::didFailToLoad(ResourceLoader* loader, NSError *error)
374 {
375     m_client->completeProgress(loader->identifier());
376     if (error)
377         m_client->dispatchDidFailLoading(activeDocumentLoader(), loader->identifier(), error);
378 }
379
380 NSURLRequest *FrameLoader::originalRequest() const
381 {
382     return activeDocumentLoader()->originalRequestCopy();
383 }
384
385 void FrameLoader::receivedMainResourceError(NSError *error, bool isComplete)
386 {
387     // Retain because the stop may release the last reference to it.
388     RefPtr<Frame> protect(m_frame);
389
390     RefPtr<DocumentLoader> loader = activeDocumentLoader();
391     
392     if (isComplete) {
393         // FIXME: Don't want to do this if an entirely new load is going, so should check
394         // that both data sources on the frame are either this or nil.
395         stop();
396         if (m_client->shouldFallBack(error))
397             handleFallbackContent();
398     }
399     
400     if (m_state == FrameStateProvisional) {
401         NSURL *failedURL = [m_provisionalDocumentLoader->originalRequestCopy() URL];
402         didNotOpenURL(failedURL);
403
404         // We might have made a page cache item, but now we're bailing out due to an error before we ever
405         // transitioned to the new page (before WebFrameState == commit).  The goal here is to restore any state
406         // so that the existing view (that wenever got far enough to replace) can continue being used.
407         Document* document = m_frame->document();
408         if (document)
409             document->setInPageCache(false);
410         m_client->invalidateCurrentItemPageCache();
411         
412         // Call clientRedirectCancelledOrFinished here so that the frame load delegate is notified that the redirect's
413         // status has changed, if there was a redirect. The frame load delegate may have saved some state about
414         // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:. Since we are definitely
415         // not going to use this provisional resource, as it was cancelled, notify the frame load delegate that the redirect
416         // has ended.
417         if (m_sentRedirectNotification)
418             clientRedirectCancelledOrFinished(false);
419     }
420     
421     
422     loader->mainReceivedError(error, isComplete);
423 }
424
425 void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument,
426     NSURLRequest *request, PassRefPtr<FormState>)
427 {
428     FrameLoader* loader = static_cast<FrameLoader*>(argument);
429     loader->continueFragmentScrollAfterNavigationPolicy(request);
430 }
431
432 void FrameLoader::continueFragmentScrollAfterNavigationPolicy(NSURLRequest *request)
433 {
434     if (!request)
435         return;
436     
437     NSURL *URL = [request URL];
438     
439     bool isRedirect = m_quickRedirectComing;
440     m_quickRedirectComing = false;
441     
442     m_documentLoader->replaceRequestURLForAnchorScroll(URL);
443     if (!isRedirect && !m_client->shouldTreatURLAsSameAsCurrent(URL)) {
444         // NB: must happen after _setURL, since we add based on the current request.
445         // Must also happen before we openURL and displace the scroll position, since
446         // adding the BF item will save away scroll state.
447         
448         // NB2:  If we were loading a long, slow doc, and the user anchor nav'ed before
449         // it was done, currItem is now set the that slow doc, and prevItem is whatever was
450         // before it.  Adding the b/f item will bump the slow doc down to prevItem, even
451         // though its load is not yet done.  I think this all works out OK, for one because
452         // we have already saved away the scroll and doc state for the long slow load,
453         // but it's not an obvious case.
454
455         m_client->addHistoryItemForFragmentScroll();
456     }
457     
458     scrollToAnchor(URL);
459     
460     if (!isRedirect)
461         // This will clear previousItem from the rest of the frame tree that didn't
462         // doing any loading. We need to make a pass on this now, since for anchor nav
463         // we'll not go through a real load and reach Completed state.
464         checkLoadComplete();
465  
466     m_client->dispatchDidChangeLocationWithinPage();
467     m_client->didFinishLoad();
468 }
469
470 void FrameLoader::opened()
471 {
472     if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
473         m_client->updateHistoryAfterClientRedirect();
474
475     if (m_client->isLoadingFromPageCache(m_documentLoader.get())) {
476         // Force a layout to update view size and thereby update scrollbars.
477         m_client->forceLayout();
478
479         const ResponseVector& responses = m_documentLoader->responses();
480         size_t count = responses.size();
481         for (size_t i = 0; i < count; i++) {
482             NSURLResponse *response = responses[i].get();
483             // FIXME: If the WebKit client changes or cancels the request, this is not respected.
484             NSError *error;
485             id identifier;
486             NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[response URL]];
487             requestFromDelegate(request, identifier, error);
488             sendRemainingDelegateMessages(identifier, response, (unsigned)[response expectedContentLength], error);
489             [request release];
490         }
491         
492         m_client->loadedFromPageCache();
493
494         m_documentLoader->setPrimaryLoadComplete(true);
495
496         // FIXME: Why only this frame and not parent frames?
497         checkLoadCompleteForThisFrame();
498     }
499 }
500
501 void FrameLoader::commitProvisionalLoad(NSDictionary *pageCache)
502 {
503     RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
504     
505     if (m_loadType != FrameLoadTypeReplace)
506         closeOldDataSources();
507     
508     if (!pageCache)
509         m_client->makeRepresentation(pdl.get());
510     
511     transitionToCommitted(pageCache);
512     
513     // Call -_clientRedirectCancelledOrFinished: here so that the frame load delegate is notified that the redirect's
514     // status has changed, if there was a redirect.  The frame load delegate may have saved some state about
515     // the redirect in its -webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:.  Since we are
516     // just about to commit a new page, there cannot possibly be a pending redirect at this point.
517     if (m_sentRedirectNotification)
518         clientRedirectCancelledOrFinished(false);
519     
520     WebCorePageState *pageState = [pageCache objectForKey:WebCorePageCacheStateKey];
521     if (PageState* frameState = [pageState impl]) {
522         open(*frameState);
523         frameState->clear();
524     } else {
525         NSURLResponse *response = pdl->response();
526     
527         NSURL *URL = [pdl->request() _webDataRequestBaseURL];
528         if (!URL)
529             URL = [response URL];
530         if (!URL || urlIsEmpty(URL))
531             URL = [NSURL URLWithString:@"about:blank"];    
532
533         m_responseMIMEType = [response MIMEType];
534         if (didOpenURL(URL)) {
535             if ([response isKindOfClass:[NSHTTPURLResponse class]])
536                 if (NSString *refresh = [[(NSHTTPURLResponse *)response allHeaderFields] objectForKey:@"Refresh"])
537                     m_responseRefreshHeader = refresh;
538             m_responseModifiedHeader = [wkGetNSURLResponseLastModifiedDate(response)
539                 descriptionWithCalendarFormat:@"%a %b %d %Y %H:%M:%S" timeZone:nil locale:nil];
540         }
541     }
542     opened();
543 }
544
545 NSURLRequest *FrameLoader::initialRequest() const
546 {
547     return activeDocumentLoader()->initialRequest();
548 }
549
550 void FrameLoader::receivedData(NSData *data)
551 {
552     activeDocumentLoader()->receivedData(data);
553 }
554
555 void FrameLoader::setRequest(NSURLRequest *request)
556 {
557     activeDocumentLoader()->setRequest(request);
558 }
559
560 void FrameLoader::setResponse(NSURLResponse *response)
561 {
562     activeDocumentLoader()->setResponse(response);
563 }
564
565 void FrameLoader::mainReceivedError(NSError *error, bool isComplete)
566 {
567     activeDocumentLoader()->mainReceivedError(error, isComplete);
568 }
569
570 void FrameLoader::notifyIconChanged()
571 {
572     ASSERT([[WebCoreIconDatabaseBridge sharedInstance] _isEnabled]);
573     NSImage *icon = [[WebCoreIconDatabaseBridge sharedInstance]
574         iconForPageURL:urlOriginalDataAsString(activeDocumentLoader()->URL().getNSURL())
575         withSize:NSMakeSize(16, 16)];
576     m_client->dispatchDidReceiveIcon(icon);
577 }
578
579 NSError *FrameLoader::cancelledError(NSURLRequest *request) const
580 {
581     return m_client->cancelledError(request);
582 }
583
584 NSError *FrameLoader::fileDoesNotExistError(NSURLResponse *response) const
585 {
586     return m_client->fileDoesNotExistError(response);    
587 }
588
589 bool FrameLoader::willUseArchive(ResourceLoader* loader, NSURLRequest *request, NSURL *originalURL) const
590 {
591     return m_client->willUseArchive(loader, request, originalURL);
592 }
593
594 void FrameLoader::handleUnimplementablePolicy(NSError *error)
595 {
596     m_delegateIsHandlingUnimplementablePolicy = true;
597     m_client->dispatchUnableToImplementPolicy(error);
598     m_delegateIsHandlingUnimplementablePolicy = false;
599 }
600
601 void FrameLoader::cannotShowMIMEType(NSURLResponse *response)
602 {
603     handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
604 }
605
606 NSError *FrameLoader::interruptionForPolicyChangeError(NSURLRequest *request)
607 {
608     return m_client->interruptForPolicyChangeError(request);
609 }
610
611 void FrameLoader::checkNavigationPolicy(NSURLRequest *newRequest,
612     NavigationPolicyDecisionFunction function, void* argument)
613 {
614     checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
615 }
616
617 void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
618 {
619     m_policyCheck.set(function, argument);
620     m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
621         MIMEType, activeDocumentLoader()->request());
622 }
623
624 bool FrameLoader::shouldReloadToHandleUnreachableURL(NSURLRequest *request)
625 {
626     NSURL *unreachableURL = [request _webDataRequestUnreachableURL];
627     if (unreachableURL == nil)
628         return false;
629
630     if (!isBackForwardLoadType(m_policyLoadType))
631         return false;
632
633     // We only treat unreachableURLs specially during the delegate callbacks
634     // for provisional load errors and navigation policy decisions. The former
635     // case handles well-formed URLs that can't be loaded, and the latter
636     // case handles malformed URLs and unknown schemes. Loading alternate content
637     // at other times behaves like a standard load.
638     DocumentLoader* compareDocumentLoader = 0;
639     if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
640         compareDocumentLoader = m_policyDocumentLoader.get();
641     else if (m_delegateIsHandlingProvisionalLoadError)
642         compareDocumentLoader = m_provisionalDocumentLoader.get();
643
644     return compareDocumentLoader && [unreachableURL isEqual:[compareDocumentLoader->request() URL]];
645 }
646
647 void FrameLoader::reloadAllowingStaleData(const String& encoding)
648 {
649     if (!m_documentLoader)
650         return;
651
652     NSMutableURLRequest *request = [m_documentLoader->request() mutableCopy];
653     KURL unreachableURL = m_documentLoader->unreachableURL();
654     if (!unreachableURL.isEmpty())
655         [request setURL:unreachableURL.getNSURL()];
656
657     [request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
658
659     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(request);
660     setPolicyDocumentLoader(loader.get());
661
662     [request release];
663
664     loader->setOverrideEncoding(encoding);
665
666     load(loader.get(), FrameLoadTypeReloadAllowingStaleData, 0);
667 }
668
669 void FrameLoader::reload()
670 {
671     if (!m_documentLoader)
672         return;
673
674     NSMutableURLRequest *initialRequest = m_documentLoader->request();
675     
676     // If a window is created by javascript, its main frame can have an empty but non-nil URL.
677     // Reloading in this case will lose the current contents (see 4151001).
678     if ([[[initialRequest URL] absoluteString] length] == 0)
679         return;
680
681     // Replace error-page URL with the URL we were trying to reach.
682     NSURL *unreachableURL = [initialRequest _webDataRequestUnreachableURL];
683     if (unreachableURL != nil)
684         initialRequest = [NSURLRequest requestWithURL:unreachableURL];
685     
686     RefPtr<DocumentLoader> loader = m_client->createDocumentLoader(initialRequest);
687     setPolicyDocumentLoader(loader.get());
688
689     NSMutableURLRequest *request = loader->request();
690
691     [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
692
693     // If we're about to re-post, set up action so the application can warn the user.
694     if ([[request HTTPMethod] isEqualToString:@"POST"])
695         loader->setTriggeringAction(NavigationAction([request URL], NavigationTypeFormResubmitted));
696
697     loader->setOverrideEncoding(m_documentLoader->overrideEncoding());
698     
699     load(loader.get(), FrameLoadTypeReload, 0);
700 }
701
702 void FrameLoader::committedLoad(DocumentLoader* loader, NSData *data)
703 {
704     m_client->committedLoad(loader, data);
705 }
706
707 void FrameLoader::setMainDocumentError(DocumentLoader* loader, NSError *error)
708 {
709     m_client->setMainDocumentError(loader, error);
710 }
711
712 void FrameLoader::mainReceivedCompleteError(DocumentLoader* loader, NSError *error)
713 {
714     loader->setPrimaryLoadComplete(true);
715     m_client->dispatchDidLoadMainResource(activeDocumentLoader());
716     checkLoadComplete();
717 }
718
719 void FrameLoader::didChangeTitle(DocumentLoader* loader)
720 {
721     m_client->didChangeTitle(loader);
722
723     // The title doesn't get communicated to the WebView until we are committed.
724     if (loader->isCommitted())
725         if (NSURL *URLForHistory = canonicalURL(loader->URLForHistory().getNSURL())) {
726             // Must update the entries in the back-forward list too.
727             // This must go through the WebFrame because it has the right notion of the current b/f item.
728             m_client->setTitle(loader->title(), URLForHistory);
729             m_client->setMainFrameDocumentReady(true); // update observers with new DOMDocument
730             m_client->dispatchDidReceiveTitle(loader->title());
731         }
732 }
733
734 void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, NSURLRequest *request,
735     PassRefPtr<FormState> formState, const String& frameName)
736 {
737     m_policyCheck.set(request, formState, frameName,
738         callContinueLoadAfterNewWindowPolicy, this);
739     m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
740         action, request, frameName);
741 }
742
743 void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
744 {
745     PolicyCheck check = m_policyCheck;
746     m_policyCheck.clear();
747
748     switch (policy) {
749         case PolicyIgnore:
750             check.clearRequest();
751             break;
752         case PolicyDownload:
753             m_client->startDownload(check.request());
754             check.clearRequest();
755             break;
756         case PolicyUse:
757             break;
758     }
759
760     check.call();
761 }
762
763 void FrameLoader::checkNavigationPolicy(NSURLRequest *request, DocumentLoader* loader,
764     PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
765 {
766     NavigationAction action = loader->triggeringAction();
767     if (action.isEmpty()) {
768         action = NavigationAction([request URL], NavigationTypeOther);
769         loader->setTriggeringAction(action);
770     }
771         
772     // Don't ask more than once for the same request or if we are loading an empty URL.
773     // This avoids confusion on the part of the client.
774     if ([request isEqual:loader->lastCheckedRequest()] || urlIsEmpty([request URL])) {
775         function(argument, request, 0);
776         return;
777     }
778     
779     // We are always willing to show alternate content for unreachable URLs;
780     // treat it like a reload so it maintains the right state for b/f list.
781     if ([request _webDataRequestUnreachableURL] != nil) {
782         if (isBackForwardLoadType(m_policyLoadType))
783             m_policyLoadType = FrameLoadTypeReload;
784         function(argument, request, 0);
785         return;
786     }
787     
788     loader->setLastCheckedRequest(request);
789
790     m_policyCheck.set(request, formState, function, argument);
791
792     m_delegateIsDecidingNavigationPolicy = true;
793     m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
794         action, request);
795     m_delegateIsDecidingNavigationPolicy = false;
796 }
797
798 void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
799 {
800     PolicyCheck check = m_policyCheck;
801     m_policyCheck.clear();
802
803     switch (policy) {
804         case PolicyIgnore:
805             check.clearRequest();
806             break;
807         case PolicyDownload:
808             m_client->startDownload(check.request());
809             check.clearRequest();
810             break;
811         case PolicyUse:
812             if (!m_client->canHandleRequest(check.request())) {
813                 handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
814                 check.clearRequest();
815             }
816             break;
817     }
818
819     check.call();
820 }
821
822 void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
823     NSURLRequest *request, PassRefPtr<FormState> formState)
824 {
825     FrameLoader* loader = static_cast<FrameLoader*>(argument);
826     loader->continueLoadAfterNavigationPolicy(request, formState);
827 }
828
829 void FrameLoader::continueLoadAfterNavigationPolicy(NSURLRequest *request,
830     PassRefPtr<FormState> formState)
831 {
832     // If we loaded an alternate page to replace an unreachableURL, we'll get in here with a
833     // nil policyDataSource because loading the alternate page will have passed
834     // through this method already, nested; otherwise, policyDataSource should still be set.
835     ASSERT(m_policyDocumentLoader || !m_provisionalDocumentLoader->unreachableURL().isEmpty());
836
837     BOOL isTargetItem = m_client->provisionalItemIsTarget();
838
839     // Two reasons we can't continue:
840     //    1) Navigation policy delegate said we can't so request is nil. A primary case of this 
841     //       is the user responding Cancel to the form repost nag sheet.
842     //    2) User responded Cancel to an alert popped up by the before unload event handler.
843     // The "before unload" event handler runs only for the main frame.
844     bool canContinue = request && (!isLoadingMainFrame() || Mac(m_frame)->shouldClose());
845
846     if (!canContinue) {
847         // If we were waiting for a quick redirect, but the policy delegate decided to ignore it, then we 
848         // need to report that the client redirect was cancelled.
849         if (m_quickRedirectComing)
850             clientRedirectCancelledOrFinished(false);
851
852         setPolicyDocumentLoader(0);
853
854         // If the navigation request came from the back/forward menu, and we punt on it, we have the 
855         // problem that we have optimistically moved the b/f cursor already, so move it back.  For sanity, 
856         // we only do this when punting a navigation for the target frame or top-level frame.  
857         if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
858             m_client->resetBackForwardList();
859
860         return;
861     }
862
863     FrameLoadType type = m_policyLoadType;
864     stopAllLoaders();
865     setProvisionalDocumentLoader(m_policyDocumentLoader.get());
866     m_loadType = type;
867     setState(FrameStateProvisional);
868
869     setPolicyDocumentLoader(0);
870
871     if (isBackForwardLoadType(type) && m_client->loadProvisionalItemFromPageCache())
872         return;
873
874     if (formState)
875         m_client->dispatchWillSubmitForm(&FrameLoader::continueAfterWillSubmitForm, formState);
876     else
877         continueAfterWillSubmitForm();
878 }
879
880 void FrameLoader::transitionToCommitted(NSDictionary *pageCache)
881 {
882     ASSERT(m_client->hasWebView());
883     ASSERT(m_state == FrameStateProvisional);
884
885     if (m_state != FrameStateProvisional)
886         return;
887
888     m_client->setCopiesOnScroll();
889     m_client->updateHistoryForCommit();
890
891     // The call to closeURL invokes the unload event handler, which can execute arbitrary
892     // JavaScript. If the script initiates a new load, we need to abandon the current load,
893     // or the two will stomp each other.
894     DocumentLoader* pdl = m_provisionalDocumentLoader.get();
895     closeDocument();
896     if (pdl != m_provisionalDocumentLoader)
897         return;
898
899     commitProvisionalLoad();
900
901     // Handle adding the URL to the back/forward list.
902     DocumentLoader* dl = m_documentLoader.get();
903     String ptitle = dl->title();
904
905     switch (m_loadType) {
906     case FrameLoadTypeForward:
907     case FrameLoadTypeBack:
908     case FrameLoadTypeIndexedBackForward:
909         if (m_client->hasBackForwardList()) {
910             m_client->updateHistoryForBackForwardNavigation();
911
912             // Create a document view for this document, or used the cached view.
913             if (pageCache)
914                 m_client->setDocumentViewFromPageCache(pageCache);
915             else
916                 m_client->makeDocumentView();
917         }
918         break;
919
920     case FrameLoadTypeReload:
921     case FrameLoadTypeSame:
922     case FrameLoadTypeReplace:
923         m_client->updateHistoryForReload();
924         m_client->makeDocumentView();
925         break;
926
927     // FIXME - just get rid of this case, and merge FrameLoadTypeReloadAllowingStaleData with the above case
928     case FrameLoadTypeReloadAllowingStaleData:
929         m_client->makeDocumentView();
930         break;
931
932     case FrameLoadTypeStandard:
933         m_client->updateHistoryForStandardLoad();
934         m_client->makeDocumentView();
935         break;
936
937     case FrameLoadTypeInternal:
938         m_client->updateHistoryForInternalLoad();
939         m_client->makeDocumentView();
940         break;
941
942     // FIXME Remove this check when dummy ds is removed (whatever "dummy ds" is).
943     // An exception should be thrown if we're in the FrameLoadTypeUninitialized state.
944     default:
945         ASSERT_NOT_REACHED();
946     }
947
948     // Tell the client we've committed this URL.
949     ASSERT(m_client->hasFrameView());
950     m_client->dispatchDidCommitLoad();
951     
952     // If we have a title let the WebView know about it.
953     if (!ptitle.isNull())
954         m_client->dispatchDidReceiveTitle(ptitle);
955 }
956
957 void FrameLoader::checkLoadCompleteForThisFrame()
958 {
959     ASSERT(m_client->hasWebView());
960
961     switch (m_state) {
962         case FrameStateProvisional: {
963             if (m_delegateIsHandlingProvisionalLoadError)
964                 return;
965
966             RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
967
968             // If we've received any errors we may be stuck in the provisional state and actually complete.
969             NSError *error = pdl->mainDocumentError();
970             if (!error)
971                 return;
972
973             // Check all children first.
974             LoadErrorResetToken *resetToken = m_client->tokenForLoadErrorReset();
975             bool shouldReset = true;
976             if (!pdl->isLoadingInAPISense()) {
977                 m_delegateIsHandlingProvisionalLoadError = true;
978                 m_client->dispatchDidFailProvisionalLoad(error);
979                 m_delegateIsHandlingProvisionalLoadError = false;
980
981                 // FIXME: can stopping loading here possibly have any effect, if isLoading is false,
982                 // which it must be to be in this branch of the if? And is it OK to just do a full-on
983                 // stopAllLoaders instead of stopLoadingSubframes?
984                 stopLoadingSubframes();
985                 pdl->stopLoading();
986
987                 // Finish resetting the load state, but only if another load hasn't been started by the
988                 // delegate callback.
989                 if (pdl == m_provisionalDocumentLoader)
990                     clearProvisionalLoad();
991                 else if (m_documentLoader) {
992                     KURL unreachableURL = m_documentLoader->unreachableURL();
993                     if (!unreachableURL.isEmpty() && unreachableURL == [pdl->request() URL])
994                         shouldReset = false;
995                 }
996             }
997             if (shouldReset)
998                 m_client->resetAfterLoadError(resetToken);
999             else
1000                 m_client->doNotResetAfterLoadError(resetToken);
1001             return;
1002         }
1003         
1004         case FrameStateCommittedPage: {
1005             DocumentLoader* dl = m_documentLoader.get();            
1006             if (dl->isLoadingInAPISense())
1007                 return;
1008
1009             markLoadComplete();
1010
1011             // FIXME: Is this subsequent work important if we already navigated away?
1012             // Maybe there are bugs because of that, or extra work we can skip because
1013             // the new page is ready.
1014
1015             m_client->forceLayoutForNonHTML();
1016              
1017             // If the user had a scroll point, scroll to it, overriding the anchor point if any.
1018             if ((isBackForwardLoadType(m_loadType) || m_loadType == FrameLoadTypeReload)
1019                     && m_client->hasBackForwardList())
1020                 m_client->restoreScrollPositionAndViewState();
1021
1022             NSError *error = dl->mainDocumentError();
1023             if (error)
1024                 m_client->dispatchDidFailLoad(error);
1025             else
1026                 m_client->dispatchDidFinishLoad();
1027
1028             m_client->progressCompleted();
1029             return;
1030         }
1031         
1032         case FrameStateComplete:
1033             // Even if already complete, we might have set a previous item on a frame that
1034             // didn't do any data loading on the past transaction. Make sure to clear these out.
1035             m_client->frameLoadCompleted();
1036             return;
1037     }
1038
1039     ASSERT_NOT_REACHED();
1040 }
1041
1042 void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
1043     NSURLRequest *request, PassRefPtr<FormState> formState, const String& frameName)
1044 {
1045     FrameLoader* loader = static_cast<FrameLoader*>(argument);
1046     loader->continueLoadAfterNewWindowPolicy(request, formState, frameName);
1047 }
1048
1049 void FrameLoader::continueLoadAfterNewWindowPolicy(NSURLRequest *request,
1050     PassRefPtr<FormState> formState, const String& frameName)
1051 {
1052     if (!request)
1053         return;
1054
1055     RefPtr<Frame> frame = m_frame;
1056     RefPtr<Frame> mainFrame = m_client->dispatchCreatePage(nil);
1057     if (!mainFrame)
1058         return;
1059
1060     mainFrame->tree()->setName(frameName);
1061     mainFrame->loader()->m_client->dispatchShow();
1062     mainFrame->loader()->setOpener(frame.get());
1063     mainFrame->loader()->load(request, NavigationAction(), FrameLoadTypeStandard, formState);
1064 }
1065
1066 void FrameLoader::sendRemainingDelegateMessages(id identifier, NSURLResponse *response, unsigned length, NSError *error)
1067 {    
1068     if (response)
1069         m_client->dispatchDidReceiveResponse(m_documentLoader.get(), identifier, response);
1070     
1071     if (length > 0)
1072         m_client->dispatchDidReceiveContentLength(m_documentLoader.get(), identifier, length);
1073     
1074     if (!error)
1075         m_client->dispatchDidFinishLoading(m_documentLoader.get(), identifier);
1076     else
1077         m_client->dispatchDidFailLoading(m_documentLoader.get(), identifier, error);
1078 }
1079
1080 NSURLRequest *FrameLoader::requestFromDelegate(NSURLRequest *request, id& identifier, NSError *& error)
1081 {
1082     ASSERT(request != nil);
1083
1084     identifier = m_client->dispatchIdentifierForInitialRequest(m_documentLoader.get(), request); 
1085     NSURLRequest *newRequest = m_client->dispatchWillSendRequest(m_documentLoader.get(), identifier, request, nil);
1086
1087     if (newRequest == nil)
1088         error = m_client->cancelledError(request);
1089     else
1090         error = nil;
1091
1092     return newRequest;
1093 }
1094
1095 void FrameLoader::loadedResourceFromMemoryCache(NSURLRequest *request, NSURLResponse *response, int length)
1096 {
1097     if (m_client->dispatchDidLoadResourceFromMemoryCache(m_documentLoader.get(), request, response, length))
1098         return;
1099
1100     id identifier;
1101     NSError *error;
1102     requestFromDelegate(request, identifier, error);
1103     sendRemainingDelegateMessages(identifier, response, length, error);
1104 }
1105
1106 void FrameLoader::post(const KURL& URL, const String& referrer, const String& frameName, const FormData& formData, 
1107     const String& contentType, Event* event, Element* form, const HashMap<String, String>& formValues)
1108 {
1109     // When posting, use the NSURLRequestReloadIgnoringCacheData load flag.
1110     // This prevents a potential bug which may cause a page with a form that uses itself
1111     // as an action to be returned from the cache without submitting.
1112
1113     // FIXME: Where's the code that implements what the comment above says?
1114
1115     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL.getNSURL()];
1116     addExtraFieldsToRequest(request, true, true);
1117
1118     setHTTPReferrer(request, referrer);
1119     [request setHTTPMethod:@"POST"];
1120     setHTTPBody(request, formData);
1121     [request setValue:contentType forHTTPHeaderField:@"Content-Type"];
1122
1123     NavigationAction action(URL, FrameLoadTypeStandard, true, event);
1124
1125     RefPtr<FormState> formState;
1126     if (form && !formValues.isEmpty())
1127         formState = FormState::create(form, formValues, m_frame);
1128
1129     if (!frameName.isEmpty()) {
1130         if (Frame* targetFrame = m_frame->tree()->find(frameName))
1131             targetFrame->loader()->load(request, action, FrameLoadTypeStandard, formState.release());
1132         else
1133             checkNewWindowPolicy(action, request, formState.release(), frameName);
1134     } else
1135         load(request, action, FrameLoadTypeStandard, formState.release());
1136
1137     [request release];
1138 }
1139
1140 void FrameLoader::detachFromParent()
1141 {
1142     RefPtr<Frame> protect(m_frame);
1143
1144     closeDocument();
1145     stopAllLoaders();
1146     m_client->detachedFromParent1();
1147     detachChildren();
1148     m_client->detachedFromParent2();
1149     setDocumentLoader(0);
1150     m_client->detachedFromParent3();
1151     if (Frame* parent = m_frame->tree()->parent())
1152         parent->tree()->removeChild(m_frame);
1153     m_frame->setView(0);
1154     [Mac(m_frame)->bridge() close];
1155     m_client->detachedFromParent4();
1156 }
1157
1158 void FrameLoader::addExtraFieldsToRequest(NSMutableURLRequest *request, bool mainResource, bool alwaysFromRequest)
1159 {
1160     applyUserAgent(request);
1161     
1162     if (m_loadType == FrameLoadTypeReload)
1163         [request setValue:@"max-age=0" forHTTPHeaderField:@"Cache-Control"];
1164     
1165     // Don't set the cookie policy URL if it's already been set.
1166     if (![request mainDocumentURL]) {
1167         if (mainResource && (isLoadingMainFrame() || alwaysFromRequest))
1168             [request setMainDocumentURL:[request URL]];
1169         else
1170             [request setMainDocumentURL:m_frame->page()->mainFrame()->loader()->url().getNSURL()];
1171     }
1172     
1173     if (mainResource)
1174         [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"];
1175 }
1176
1177 bool FrameLoader::isReloading() const
1178 {
1179     return [documentLoader()->request() cachePolicy] == NSURLRequestReloadIgnoringCacheData;
1180 }
1181
1182 String FrameLoader::referrer() const
1183 {
1184     return [documentLoader()->request() valueForHTTPHeaderField:@"Referer"];
1185 }
1186
1187 void FrameLoader::loadEmptyDocumentSynchronously()
1188 {
1189     NSURL *url = [[NSURL alloc] initWithString:@""];
1190     NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
1191     load(request);
1192     [request release];
1193     [url release];
1194 }
1195
1196 void FrameLoader::loadResourceSynchronously(const ResourceRequest& request, Vector<char>& data, ResourceResponse& r)
1197 {
1198     NSURL *URL = request.url().getNSURL();
1199
1200     // Since this is a subresource, we can load any URL (we ignore the return value).
1201     // But we still want to know whether we should hide the referrer or not, so we call the canLoadURL method.
1202     String referrer = m_outgoingReferrer;
1203     bool hideReferrer;
1204     canLoad(URL, referrer, hideReferrer);
1205     if (hideReferrer)
1206         referrer = String();
1207     
1208     NSMutableURLRequest *initialRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
1209     [initialRequest setTimeoutInterval:10];
1210     
1211     [initialRequest setHTTPMethod:request.httpMethod()];
1212     
1213     if (!request.httpBody().isEmpty())        
1214         setHTTPBody(initialRequest, request.httpBody());
1215     
1216     HTTPHeaderMap::const_iterator end = request.httpHeaderFields().end();
1217     for (HTTPHeaderMap::const_iterator it = request.httpHeaderFields().begin(); it != end; ++it)
1218         [initialRequest addValue:it->second forHTTPHeaderField:it->first];
1219     
1220     if (isConditionalRequest(initialRequest))
1221         [initialRequest setCachePolicy:NSURLRequestReloadIgnoringCacheData];
1222     else
1223         [initialRequest setCachePolicy:[documentLoader()->request() cachePolicy]];
1224     
1225     if (!referrer.isEmpty())
1226         setHTTPReferrer(initialRequest, referrer);
1227     
1228     [initialRequest setMainDocumentURL:[m_frame->page()->mainFrame()->loader()->documentLoader()->request() URL]];
1229     applyUserAgent(initialRequest);
1230     
1231     NSError *error = nil;
1232     id identifier = nil;    
1233     NSURLRequest *newRequest = requestFromDelegate(initialRequest, identifier, error);
1234     
1235     NSURLResponse *response = nil;
1236     NSData *result = nil;
1237     if (error == nil) {
1238         ASSERT(newRequest != nil);
1239         result = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&response error:&error];
1240     }
1241     
1242     [initialRequest release];
1243
1244     if (error == nil)
1245         getResourceResponse(r, response);
1246     else {
1247         r = ResourceResponse(URL, String(), 0, String(), String());
1248         if ([error domain] == NSURLErrorDomain)
1249             r.setHTTPStatusCode([error code]);
1250         else
1251             r.setHTTPStatusCode(404);
1252     }
1253     
1254     sendRemainingDelegateMessages(identifier, response, [result length], error);
1255     
1256     data.resize([result length]);
1257     memcpy(data.data(), [result bytes], [result length]);
1258 }
1259
1260 Frame* FrameLoader::createFrame(const KURL& url, const String& name, Element* ownerElement, const String& referrer)
1261 {
1262     BOOL allowsScrolling = YES;
1263     int marginWidth = -1;
1264     int marginHeight = -1;
1265     if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag)) {
1266         HTMLFrameElement* o = static_cast<HTMLFrameElement*>(ownerElement);
1267         allowsScrolling = o->scrollingMode() != ScrollbarAlwaysOff;
1268         marginWidth = o->getMarginWidth();
1269         marginHeight = o->getMarginHeight();
1270     }
1271
1272     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1273     
1274     return [[Mac(m_frame)->bridge() createChildFrameNamed:name
1275                                                              withURL:url.getNSURL()
1276                                                             referrer:referrer 
1277                                                           ownerElement:ownerElement
1278                                                      allowsScrolling:allowsScrolling
1279                                                          marginWidth:marginWidth
1280                                                         marginHeight:marginHeight] _frame];
1281
1282     END_BLOCK_OBJC_EXCEPTIONS;
1283     return 0;
1284 }
1285
1286 ObjectContentType FrameLoader::objectContentType(const KURL& url, const String& mimeType)
1287 {
1288     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1289     return (ObjectContentType)[Mac(m_frame)->bridge() determineObjectFromMIMEType:mimeType URL:url.getNSURL()];
1290     END_BLOCK_OBJC_EXCEPTIONS;
1291     return ObjectContentNone;
1292 }
1293
1294 static NSArray* nsArray(const Vector<String>& vector)
1295 {
1296     unsigned len = vector.size();
1297     NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1298     for (unsigned x = 0; x < len; x++)
1299         [array addObject:vector[x]];
1300     return array;
1301 }
1302
1303 Widget* FrameLoader::createPlugin(Element* element, const KURL& url,
1304     const Vector<String>& paramNames, const Vector<String>& paramValues,
1305     const String& mimeType)
1306 {
1307     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1308     return new Widget([Mac(m_frame)->bridge() viewForPluginWithURL:url.getNSURL()
1309                                   attributeNames:nsArray(paramNames)
1310                                   attributeValues:nsArray(paramValues)
1311                                   MIMEType:mimeType
1312                                   DOMElement:[DOMElement _elementWith:element]
1313                                 loadManually:m_frame->document()->isPluginDocument()]);
1314     END_BLOCK_OBJC_EXCEPTIONS;
1315     return 0;
1316 }
1317
1318 void FrameLoader::redirectDataToPlugin(Widget* pluginWidget)
1319 {
1320     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1321     [Mac(m_frame)->bridge() redirectDataToPlugin:pluginWidget->getView()];
1322     END_BLOCK_OBJC_EXCEPTIONS;
1323 }
1324
1325 Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, Element* element, const HashMap<String, String>& args)
1326 {
1327     Widget* result = new Widget;
1328     
1329     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1330     
1331     NSMutableArray *attributeNames = [[NSMutableArray alloc] init];
1332     NSMutableArray *attributeValues = [[NSMutableArray alloc] init];
1333     
1334     DeprecatedString baseURLString;
1335     HashMap<String, String>::const_iterator end = args.end();
1336     for (HashMap<String, String>::const_iterator it = args.begin(); it != end; ++it) {
1337         if (it->first.lower() == "baseurl")
1338             baseURLString = it->second.deprecatedString();
1339         [attributeNames addObject:it->first];
1340         [attributeValues addObject:it->second];
1341     }
1342     
1343     if (baseURLString.isEmpty())
1344         baseURLString = m_frame->document()->baseURL();
1345
1346     result->setView([Mac(m_frame)->bridge() viewForJavaAppletWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1347                                          attributeNames:attributeNames
1348                                         attributeValues:attributeValues
1349                                                 baseURL:completeURL(baseURLString).getNSURL()
1350                                              DOMElement:[DOMElement _elementWith:element]]);
1351     [attributeNames release];
1352     [attributeValues release];
1353     m_frame->view()->addChild(result);
1354     
1355     END_BLOCK_OBJC_EXCEPTIONS;
1356     
1357     return result;
1358 }
1359
1360 void FrameLoader::partClearedInBegin()
1361 {
1362     if (m_frame->javaScriptEnabled())
1363         [Mac(m_frame)->bridge() windowObjectCleared];
1364 }
1365
1366 void FrameLoader::saveDocumentState()
1367 {
1368     // Do not save doc state if the page has a password field and a form that would be submitted via https.
1369     Document* document = m_frame->document();
1370     if (!(document && document->hasPasswordField() && document->hasSecureForm())) {
1371         BEGIN_BLOCK_OBJC_EXCEPTIONS;
1372         [Mac(m_frame)->bridge() saveDocumentState];
1373         END_BLOCK_OBJC_EXCEPTIONS;
1374     }
1375 }
1376
1377 void FrameLoader::restoreDocumentState()
1378 {
1379     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1380     [Mac(m_frame)->bridge() restoreDocumentState];
1381     END_BLOCK_OBJC_EXCEPTIONS;
1382 }
1383
1384 String FrameLoader::overrideMediaType() const
1385 {
1386     NSString *overrideType = [Mac(m_frame)->bridge() overrideMediaType];
1387     if (overrideType)
1388         return overrideType;
1389     return String();
1390 }
1391
1392 NSData *FrameLoader::mainResourceData() const
1393 {
1394     if (!m_mainResourceLoader)
1395         return nil;
1396     return m_mainResourceLoader->resourceData();
1397 }
1398
1399 bool FrameLoader::canGoBackOrForward(int distance) const
1400 {
1401     return [Mac(m_frame)->bridge() canGoBackOrForward:distance];
1402 }
1403
1404 KURL FrameLoader::originalRequestURL() const
1405 {
1406     return [activeDocumentLoader()->initialRequest() URL];
1407 }
1408
1409 int FrameLoader::getHistoryLength()
1410 {
1411     return [Mac(m_frame)->bridge() historyLength];
1412 }
1413
1414 void FrameLoader::goBackOrForward(int distance)
1415 {
1416     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1417     [Mac(m_frame)->bridge() goBackOrForward:distance];
1418     END_BLOCK_OBJC_EXCEPTIONS;
1419 }
1420
1421 KURL FrameLoader::historyURL(int distance)
1422 {
1423     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1424     return [Mac(m_frame)->bridge() historyURL:distance];
1425     END_BLOCK_OBJC_EXCEPTIONS;
1426     return KURL();
1427 }
1428
1429 void FrameLoader::didFinishLoad(ResourceLoader* loader)
1430 {    
1431     m_client->completeProgress(loader->identifier());
1432     m_client->dispatchDidFinishLoading(activeDocumentLoader(), loader->identifier());
1433 }
1434
1435 PolicyCheck::PolicyCheck()
1436     : m_navigationFunction(0)
1437     , m_newWindowFunction(0)
1438     , m_contentFunction(0)
1439 {
1440 }
1441
1442 void PolicyCheck::clear()
1443 {
1444     clearRequest();
1445     m_navigationFunction = 0;
1446     m_newWindowFunction = 0;
1447     m_contentFunction = 0;
1448 }
1449
1450 void PolicyCheck::set(NSURLRequest *request, PassRefPtr<FormState> formState,
1451     NavigationPolicyDecisionFunction function, void* argument)
1452 {
1453     m_request = request;
1454     m_formState = formState;
1455     m_frameName = String();
1456
1457     m_navigationFunction = function;
1458     m_newWindowFunction = 0;
1459     m_contentFunction = 0;
1460     m_argument = argument;
1461 }
1462
1463 void PolicyCheck::set(NSURLRequest *request, PassRefPtr<FormState> formState,
1464     const String& frameName, NewWindowPolicyDecisionFunction function, void* argument)
1465 {
1466     m_request = request;
1467     m_formState = formState;
1468     m_frameName = frameName;
1469
1470     m_navigationFunction = 0;
1471     m_newWindowFunction = function;
1472     m_contentFunction = 0;
1473     m_argument = argument;
1474 }
1475
1476 void PolicyCheck::set(ContentPolicyDecisionFunction function, void* argument)
1477 {
1478     m_request = nil;
1479     m_formState = 0;
1480     m_frameName = String();
1481
1482     m_navigationFunction = 0;
1483     m_newWindowFunction = 0;
1484     m_contentFunction = function;
1485     m_argument = argument;
1486 }
1487
1488 void PolicyCheck::call()
1489 {
1490     if (m_navigationFunction)
1491         m_navigationFunction(m_argument, m_request.get(), m_formState.get());
1492     if (m_newWindowFunction)
1493         m_newWindowFunction(m_argument, m_request.get(), m_formState.get(), m_frameName);
1494     ASSERT(!m_contentFunction);
1495 }
1496
1497 void PolicyCheck::call(PolicyAction action)
1498 {
1499     ASSERT(!m_navigationFunction);
1500     ASSERT(!m_newWindowFunction);
1501     ASSERT(m_contentFunction);
1502     m_contentFunction(m_argument, action);
1503 }
1504
1505 void PolicyCheck::clearRequest()
1506 {
1507     m_request = nil;
1508     m_formState = 0;
1509     m_frameName = String();
1510 }
1511
1512 }