Reviewed by Maciej.
[WebKit-https.git] / WebKit / WebCoreSupport / WebFrameLoaderClient.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 "WebFrameLoaderClient.h"
30
31 // Terrible hack; lets us get at the WebFrame private structure.
32 #define private public
33 #import "WebFrame.h"
34 #undef private
35
36 #import "DOMElementInternal.h"
37 #import "WebBackForwardList.h"
38 #import "WebChromeClient.h"
39 #import "WebDataSourceInternal.h"
40 #import "WebPolicyDelegatePrivate.h"
41 #import "WebDocumentInternal.h"
42 #import "WebDocumentLoaderMac.h"
43 #import "WebDownloadInternal.h"
44 #import "WebElementDictionary.h"
45 #import "WebFormDelegate.h"
46 #import "WebFrameBridge.h"
47 #import "WebFrameInternal.h"
48 #import "WebFrameLoadDelegate.h"
49 #import "WebFrameViewInternal.h"
50 #import "WebHTMLRepresentation.h"
51 #import "WebHTMLView.h"
52 #import "WebHistoryItemInternal.h"
53 #import "WebHistoryItemPrivate.h"
54 #import "WebHistoryPrivate.h"
55 #import "WebIconDatabaseInternal.h"
56 #import "WebKitErrorsPrivate.h"
57 #import "WebKitLogging.h"
58 #import "WebKitNSStringExtras.h"
59 #import "WebNSURLExtras.h"
60 #import "WebPanelAuthenticationHandler.h"
61 #import "WebPolicyDelegate.h"
62 #import "WebPreferences.h"
63 #import "WebResourceLoadDelegate.h"
64 #import "WebResourcePrivate.h"
65 #import "WebScriptDebugServerPrivate.h"
66 #import "WebUIDelegate.h"
67 #import "WebViewInternal.h"
68 #import <WebCore/AuthenticationMac.h>
69 #import <WebCore/BlockExceptions.h>
70 #import <WebCore/CachedPage.h>
71 #import <WebCore/Chrome.h>
72 #import <WebCore/Document.h>
73 #import <WebCore/DocumentLoader.h>
74 #import <WebCore/EventHandler.h>
75 #import <WebCore/FormState.h>
76 #import <WebCore/FrameLoader.h>
77 #import <WebCore/FrameLoaderTypes.h>
78 #import <WebCore/Frame.h>
79 #import <WebCore/FrameTree.h>
80 #import <WebCore/HistoryItem.h>
81 #import <WebCore/HitTestResult.h>
82 #import <WebCore/HTMLFormElement.h>
83 #import <WebCore/IconDatabase.h>
84 #import <WebCore/LoaderNSURLExtras.h>
85 #import <WebCore/MouseEvent.h>
86 #import <WebCore/Page.h>
87 #import <WebCore/PlatformString.h>
88 #import <WebCore/ResourceError.h>
89 #import <WebCore/ResourceHandle.h>
90 #import <WebCore/ResourceLoader.h>
91 #import <WebCore/ResourceRequest.h>
92 #import <WebCore/WebCoreFrameBridge.h>
93 #import <WebCore/WebCoreObjCExtras.h>
94 #import <WebCore/SharedBuffer.h>
95 #import <WebCore/Widget.h>
96 #import <WebKit/DOMElement.h>
97 #import <WebKit/DOMHTMLFormElement.h>
98 #import <WebKitSystemInterface.h>
99 #import <wtf/PassRefPtr.h>
100
101 using namespace WebCore;
102
103 // SPI for NSURLDownload
104 // Needed for <rdar://problem/5121850> 
105 @interface NSURLDownload (NSURLDownloadPrivate)
106
107 - (void)_setOriginatingURL:(NSURL *)url;
108 - (NSURL *)_originatingURL;
109
110 @end
111
112 // FIXME: This is unnecessary after <rdar://problem/5208329>
113 @interface WebHistoryItem (WebHistoryItemPrivate)
114
115 - (BOOL)_wasUserGesture;
116
117 @end
118
119 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener>
120 {
121     Frame* m_frame;
122 }
123 - (id)initWithWebCoreFrame:(Frame*)frame;
124 - (void)invalidate;
125 @end
126
127 static inline WebDataSource *dataSource(DocumentLoader* loader)
128 {
129     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
130 }
131
132 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
133     : m_webFrame(webFrame)
134     , m_policyFunction(0)
135     , m_archivedResourcesDeliveryTimer(this, &WebFrameLoaderClient::deliverArchivedResources)
136 {
137 }
138
139 void WebFrameLoaderClient::frameLoaderDestroyed()
140 {
141     delete this;
142 }
143
144 bool WebFrameLoaderClient::hasWebView() const
145 {
146     return [m_webFrame.get() webView] != nil;
147 }
148
149 bool WebFrameLoaderClient::hasFrameView() const
150 {
151     return m_webFrame->_private->webFrameView != nil;
152 }
153
154 bool WebFrameLoaderClient::privateBrowsingEnabled() const
155 {
156     return [[getWebView(m_webFrame.get()) preferences] privateBrowsingEnabled];
157 }
158
159 void WebFrameLoaderClient::makeDocumentView()
160 {
161     WebFrameView *v = m_webFrame->_private->webFrameView;
162     WebDataSource *ds = [m_webFrame.get() _dataSource];
163
164     NSView <WebDocumentView> *documentView = [v _makeDocumentViewForDataSource:ds];
165     if (!documentView)
166         return;
167
168     WebFrameBridge *bridge = m_webFrame->_private->bridge;
169
170     // FIXME: We could save work and not do this for a top-level view that is not a WebHTMLView.
171     [bridge createFrameViewWithNSView:documentView marginWidth:[v _marginWidth] marginHeight:[v _marginHeight]];
172     [m_webFrame.get() _updateBackground];
173     [bridge installInFrame:[v _scrollView]];
174
175     // Call setDataSource on the document view after it has been placed in the view hierarchy.
176     // This what we for the top-level view, so should do this for views in subframes as well.
177     [documentView setDataSource:ds];
178 }
179
180 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
181 {
182     [dataSource(loader) _makeRepresentation];
183 }
184
185 void WebFrameLoaderClient::setDocumentViewFromCachedPage(CachedPage* cachedPage)
186 {
187     DocumentLoader* cachedDocumentLoader = cachedPage->documentLoader();
188     ASSERT(cachedDocumentLoader);
189     cachedDocumentLoader->setFrame(core(m_webFrame.get()));
190     NSView <WebDocumentView> *cachedView = cachedPage->documentView();
191     ASSERT(cachedView != nil);
192     [cachedView setDataSource:dataSource(cachedDocumentLoader)];
193     [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
194 }
195
196 void WebFrameLoaderClient::forceLayout()
197 {
198     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
199     if ([view isKindOfClass:[WebHTMLView class]])
200         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
201     [view setNeedsLayout:YES];
202     [view layout];
203 }
204
205 void WebFrameLoaderClient::forceLayoutForNonHTML()
206 {
207     WebFrameView *thisView = m_webFrame->_private->webFrameView;
208     NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
209     ASSERT(thisDocumentView != nil);
210     
211     // Tell the just loaded document to layout.  This may be necessary
212     // for non-html content that needs a layout message.
213     if (!([[m_webFrame.get() _dataSource] _isDocumentHTML])) {
214         [thisDocumentView setNeedsLayout:YES];
215         [thisDocumentView layout];
216         [thisDocumentView setNeedsDisplay:YES];
217     }
218 }
219
220 void WebFrameLoaderClient::setCopiesOnScroll()
221 {
222     [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
223 }
224
225 void WebFrameLoaderClient::detachedFromParent2()
226 {
227     [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
228 }
229
230 void WebFrameLoaderClient::detachedFromParent3()
231 {
232     [m_webFrame->_private->webFrameView release];
233     m_webFrame->_private->webFrameView = nil;
234 }
235
236 void WebFrameLoaderClient::detachedFromParent4()
237 {
238     m_webFrame->_private->bridge = nil;
239 }
240
241 void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceResponse& response)
242 {
243     id proxy = handle->releaseProxy();
244     ASSERT(proxy);
245     
246     WebView *webView = getWebView(m_webFrame.get());
247     WebDownload *download = [WebDownload _downloadWithLoadingConnection:handle->connection()
248                                                                 request:request.nsURLRequest()
249                                                                response:response.nsURLResponse()
250                                                                delegate:[webView downloadDelegate]
251                                                                   proxy:proxy]; 
252     NSURL *originalURL = nil;
253     WebBackForwardList *history = [webView backForwardList];
254     WebHistoryItem *currentItem = nil;
255     int backListCount = [history backListCount];
256     int backCount = 0;
257     
258     // find the first item in the history that was originated
259     // by the user
260     while (backListCount > 0 && !originalURL) {
261         currentItem = [history itemAtIndex:backCount--];
262         
263         if (![currentItem respondsToSelector:@selector(_wasUserGesture)] || [currentItem _wasUserGesture])
264             originalURL = [currentItem URL];
265     }
266
267     if (originalURL && [download respondsToSelector:@selector(_setOriginatingURL:)])
268         [download _setOriginatingURL:originalURL];
269 }
270
271 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
272 {
273     WebView *webView = getWebView(m_webFrame.get());
274
275     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
276     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
277     if (!implementations.delegateImplementsDidLoadResourceFromMemoryCache)
278         return false;
279
280     implementations.didLoadResourceFromMemoryCacheFunc(resourceLoadDelegate, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), webView, request.nsURLRequest(), response.nsURLResponse(), length, dataSource(loader));
281     return true;
282 }
283
284 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
285 {
286     WebView *webView = getWebView(m_webFrame.get());
287     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
288     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
289
290     id object;
291     BOOL shouldRelease = NO;
292     if (implementations.delegateImplementsIdentifierForRequest)
293         object = implementations.identifierForRequestFunc(resourceLoadDelegate, @selector(webView:identifierForInitialRequest:fromDataSource:), webView, request.nsURLRequest(), dataSource(loader));
294     else {
295         object = [[NSObject alloc] init];
296         shouldRelease = YES;
297     }
298
299     [webView _addObject:object forIdentifier:identifier];
300
301     if (shouldRelease)
302         [object release];
303 }
304
305 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
306 {
307     WebView *webView = getWebView(m_webFrame.get());
308     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
309     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
310
311     if (redirectResponse.isNull())
312         static_cast<WebDocumentLoaderMac*>(loader)->increaseLoadCount(identifier);
313
314     if (implementations.delegateImplementsWillSendRequest)
315         request = implementations.willSendRequestFunc(resourceLoadDelegate, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), webView, [webView _objectForIdentifier:identifier], request.nsURLRequest(), redirectResponse.nsURLResponse(), dataSource(loader));
316 }
317
318 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
319 {
320     WebView *webView = getWebView(m_webFrame.get());
321     id resourceLoadDelegate = [webView resourceLoadDelegate];
322     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
323
324     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
325
326     if (implementations.delegateImplementsDidReceiveAuthenticationChallenge) {
327         if (id resource = [webView _objectForIdentifier:identifier]) {
328             [resourceLoadDelegate webView:webView resource:resource didReceiveAuthenticationChallenge:webChallenge fromDataSource:dataSource(loader)];
329             return;
330         }
331     }
332
333     NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
334     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window];
335 }
336
337 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge)
338 {
339     WebView *webView = getWebView(m_webFrame.get());
340     id resourceLoadDelegate = [webView resourceLoadDelegate];
341     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
342
343     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
344
345     if (implementations.delegateImplementsDidCancelAuthenticationChallenge) {
346         if (id resource = [webView _objectForIdentifier:identifier]) {
347             [resourceLoadDelegate webView:webView resource:resource didCancelAuthenticationChallenge:webChallenge fromDataSource:dataSource(loader)];
348             return;
349         }
350     }
351
352     [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge];
353 }
354
355 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
356 {
357     WebView *webView = getWebView(m_webFrame.get());
358     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
359     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
360
361     if (implementations.delegateImplementsDidReceiveResponse) {
362         if (id resource = [webView _objectForIdentifier:identifier])
363             implementations.didReceiveResponseFunc(resourceLoadDelegate, @selector(webView:resource:didReceiveResponse:fromDataSource:), webView, resource, response.nsURLResponse(), dataSource(loader));
364     }
365 }
366
367 NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader* loader, unsigned long identifier, NSCachedURLResponse* response) const
368 {
369     WebView *webView = getWebView(m_webFrame.get());
370     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
371     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
372     if (implementations.delegateImplementsWillCacheResponse) {
373         if (id resource = [webView _objectForIdentifier:identifier]) 
374             return implementations.willCacheResponseFunc(resourceLoadDelegate, @selector(webView:resource:willCacheResponse:fromDataSource:), webView, resource, response, dataSource(loader));
375     }
376
377     return response;
378 }
379
380 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int lengthReceived)
381 {
382     WebView *webView = getWebView(m_webFrame.get());
383     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
384     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
385
386     if (implementations.delegateImplementsDidReceiveContentLength) {
387         if (id resource = [webView _objectForIdentifier:identifier]) 
388             implementations.didReceiveContentLengthFunc(resourceLoadDelegate, @selector(webView:resource:didReceiveContentLength:fromDataSource:), webView, resource, (WebNSUInteger)lengthReceived, dataSource(loader));
389     }
390 }
391
392 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
393 {
394     WebView *webView = getWebView(m_webFrame.get());
395     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
396     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
397
398     if (implementations.delegateImplementsDidFinishLoadingFromDataSource) {
399         if (id resource = [webView _objectForIdentifier:identifier])
400             implementations.didFinishLoadingFromDataSourceFunc(resourceLoadDelegate, @selector(webView:resource:didFinishLoadingFromDataSource:), webView, resource, dataSource(loader));
401     }
402     [webView _removeObjectForIdentifier:identifier];
403
404     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
405 }
406
407 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const WebCore::ResourceError& error)
408 {
409     WebView *webView = getWebView(m_webFrame.get());
410     id resourceLoadDelegate = WebViewGetResourceLoadDelegate(webView);
411     WebResourceDelegateImplementationCache implementations = WebViewGetResourceLoadDelegateImplementations(webView);
412
413     if (implementations.delegateImplementsDidFailLoadingWithErrorFromDataSource) {
414         if (id resource = [webView _objectForIdentifier:identifier])
415             implementations.didFailLoadingWithErrorFromDataSourceFunc(resourceLoadDelegate, @selector(webView:resource:didFailLoadingWithError:fromDataSource:), webView, resource, error, dataSource(loader));
416     }
417     [webView _removeObjectForIdentifier:identifier];
418
419     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
420 }
421
422 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
423 {
424     WebView *webView = getWebView(m_webFrame.get());
425     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
426     if (implementations.delegateImplementsDidHandleOnloadEventsForFrame) {
427         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
428         implementations.didHandleOnloadEventsForFrameFunc(frameLoadDelegate, @selector(webView:didHandleOnloadEventsForFrame:), webView, m_webFrame.get());
429     }
430 }
431
432 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
433 {
434     WebView *webView = getWebView(m_webFrame.get());
435     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
436     if (implementations.delegateImplementsDidReceiveServerRedirectForProvisionalLoadForFrame) {
437         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
438         implementations.didReceiveServerRedirectForProvisionalLoadForFrameFunc(frameLoadDelegate, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:), webView, m_webFrame.get());
439     }
440 }
441
442 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
443 {
444     WebView *webView = getWebView(m_webFrame.get());
445     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
446     if (implementations.delegateImplementsDidCancelClientRedirectForFrame) {
447         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
448         implementations.didCancelClientRedirectForFrameFunc(frameLoadDelegate, @selector(webView:didCancelClientRedirectForFrame:), webView, m_webFrame.get());
449     }
450 }
451
452 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& URL, double delay, double fireDate)
453 {
454     WebView *webView = getWebView(m_webFrame.get());
455     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
456     if (implementations.delegateImplementsWillPerformClientRedirectToURLDelayFireDateForFrame) {
457         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
458         implementations.willPerformClientRedirectToURLDelayFireDateForFrameFunc(frameLoadDelegate, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:), webView, URL.getNSURL(), delay, [NSDate dateWithTimeIntervalSince1970:fireDate], m_webFrame.get());
459     }
460 }
461
462 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
463 {
464     WebView *webView = getWebView(m_webFrame.get());
465     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
466     if (implementations.delegateImplementsDidChangeLocationWithinPageForFrame) {
467         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
468         implementations.didChangeLocationWithinPageForFrameFunc(frameLoadDelegate, @selector(webView:didChangeLocationWithinPageForFrame:), webView, m_webFrame.get());
469     }
470 }
471
472 void WebFrameLoaderClient::dispatchWillClose()
473 {
474     WebView *webView = getWebView(m_webFrame.get());   
475     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
476     if (implementations.delegateImplementsWillCloseFrame) {
477         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
478         implementations.willCloseFrameFunc(frameLoadDelegate, @selector(webView:willCloseFrame:), webView, m_webFrame.get());
479     }
480 }
481
482 void WebFrameLoaderClient::dispatchDidReceiveIcon()
483 {
484     ASSERT([m_webFrame.get() _isMainFrame]);
485     WebView *webView = getWebView(m_webFrame.get());   
486
487     // FIXME: This willChangeValueForKey call is too late, because the icon has already changed by now.
488     [webView _willChangeValueForKey:_WebMainFrameIconKey];
489
490     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
491     if (implementations.delegateImplementsDidReceiveIconForFrame) {
492         Image* image = iconDatabase()->iconForPageURL(core(m_webFrame.get())->loader()->url().url(), IntSize(16, 16));
493         if (NSImage *icon = webGetNSImage(image, NSMakeSize(16, 16))) {
494             id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
495             implementations.didReceiveIconForFrameFunc(frameLoadDelegate, @selector(webView:didReceiveIcon:forFrame:), webView, icon, m_webFrame.get());
496         }
497     }
498
499     [webView _didChangeValueForKey:_WebMainFrameIconKey];
500 }
501
502 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
503 {
504     WebView *webView = getWebView(m_webFrame.get());   
505     [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
506
507     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
508     if (implementations.delegateImplementsDidStartProvisionalLoadForFrame) {
509         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
510         implementations.didStartProvisionalLoadForFrameFunc(frameLoadDelegate, @selector(webView:didStartProvisionalLoadForFrame:), webView, m_webFrame.get());
511     }
512 }
513
514 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
515 {
516     WebView *webView = getWebView(m_webFrame.get());   
517     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
518     if (implementations.delegateImplementsDidReceiveTitleForFrame) {
519         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
520         implementations.didReceiveTitleForFrameFunc(frameLoadDelegate, @selector(webView:didReceiveTitle:forFrame:), webView, title, m_webFrame.get());
521     }
522 }
523
524 void WebFrameLoaderClient::dispatchDidCommitLoad()
525 {
526     // Tell the client we've committed this URL.
527     ASSERT([m_webFrame->_private->webFrameView documentView] != nil);
528     
529     WebView *webView = getWebView(m_webFrame.get());   
530     [webView _didCommitLoadForFrame:m_webFrame.get()];
531
532     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
533     if (implementations.delegateImplementsDidCommitLoadForFrame) {
534         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
535         implementations.didCommitLoadForFrameFunc(frameLoadDelegate, @selector(webView:didCommitLoadForFrame:), webView, m_webFrame.get());
536     }
537 }
538
539 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
540 {
541     WebView *webView = getWebView(m_webFrame.get());   
542     [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
543     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
544     if (implementations.delegateImplementsDidFailProvisionalLoadWithErrorForFrame) {
545         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
546         implementations.didFailProvisionalLoadWithErrorForFrameFunc(frameLoadDelegate, @selector(webView:didFailProvisionalLoadWithError:forFrame:), webView, error, m_webFrame.get());
547     }
548     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
549 }
550
551 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
552 {
553     WebView *webView = getWebView(m_webFrame.get());   
554     [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
555
556     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
557     if (implementations.delegateImplementsDidFailLoadWithErrorForFrame) {
558         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
559         implementations.didFailLoadWithErrorForFrameFunc(frameLoadDelegate, @selector(webView:didFailLoadWithError:forFrame:), webView, error, m_webFrame.get());
560     }
561
562     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
563 }
564
565 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
566 {
567     WebView *webView = getWebView(m_webFrame.get());
568     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
569     if (implementations.delegateImplementsDidFinishDocumentLoadForFrame) {
570         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
571         implementations.didFinishDocumentLoadForFrameFunc(frameLoadDelegate, @selector(webView:didFinishDocumentLoadForFrame:), webView, m_webFrame.get());
572     }
573 }
574
575 void WebFrameLoaderClient::dispatchDidFinishLoad()
576 {
577     WebView *webView = getWebView(m_webFrame.get());   
578     [webView _didFinishLoadForFrame:m_webFrame.get()];
579
580     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
581     if (implementations.delegateImplementsDidFinishLoadForFrame) {
582         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
583         implementations.didFinishLoadForFrameFunc(frameLoadDelegate, @selector(webView:didFinishLoadForFrame:), webView, m_webFrame.get());
584     }
585
586     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
587 }
588
589 void WebFrameLoaderClient::dispatchDidFirstLayout()
590 {
591     WebView *webView = getWebView(m_webFrame.get());
592     WebFrameLoadDelegateImplementationCache implementations = WebViewGetFrameLoadDelegateImplementations(webView);
593     if (implementations.delegateImplementsDidFirstLayoutInFrame) {
594         id frameLoadDelegate = WebViewGetFrameLoadDelegate(webView);
595         implementations.didFirstLayoutInFrameFunc(frameLoadDelegate, @selector(webView:didFirstLayoutInFrame:), webView, m_webFrame.get());
596     }
597 }
598
599 Frame* WebFrameLoaderClient::dispatchCreatePage()
600 {
601     WebView *currentWebView = getWebView(m_webFrame.get());
602     id wd = [currentWebView UIDelegate];
603     if ([wd respondsToSelector:@selector(webView:createWebViewWithRequest:)])
604         return core([[wd webView:currentWebView createWebViewWithRequest:nil] mainFrame]);
605     return 0;
606 }
607
608 void WebFrameLoaderClient::dispatchShow()
609 {
610     WebView *webView = getWebView(m_webFrame.get());
611     [[webView _UIDelegateForwarder] webViewShow:webView];
612 }
613
614 void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function,
615     const String& MIMEType, const ResourceRequest& request)
616 {
617     WebView *webView = getWebView(m_webFrame.get());
618
619     [[webView _policyDelegateForwarder] webView:webView
620                         decidePolicyForMIMEType:MIMEType
621                                         request:request.nsURLRequest()
622                                           frame:m_webFrame.get()
623                                decisionListener:setUpPolicyListener(function).get()];
624 }
625
626 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,
627     const NavigationAction& action, const ResourceRequest& request, const String& frameName)
628 {
629     WebView *webView = getWebView(m_webFrame.get());
630     [[webView _policyDelegateForwarder] webView:webView
631             decidePolicyForNewWindowAction:actionDictionary(action)
632                                    request:request.nsURLRequest()
633                               newFrameName:frameName
634                           decisionListener:setUpPolicyListener(function).get()];
635 }
636
637 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,
638     const NavigationAction& action, const ResourceRequest& request)
639 {
640     WebView *webView = getWebView(m_webFrame.get());
641     [[webView _policyDelegateForwarder] webView:webView
642                 decidePolicyForNavigationAction:actionDictionary(action)
643                                         request:request.nsURLRequest()
644                                           frame:m_webFrame.get()
645                                decisionListener:setUpPolicyListener(function).get()];
646 }
647
648 void WebFrameLoaderClient::cancelPolicyCheck()
649 {
650     [m_policyListener.get() invalidate];
651     m_policyListener = nil;
652     m_policyFunction = 0;
653 }
654
655 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
656 {
657     WebView *webView = getWebView(m_webFrame.get());
658     [[webView _policyDelegateForwarder] webView:webView
659         unableToImplementPolicyWithError:error frame:m_webFrame.get()];    
660 }
661
662 void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
663 {
664     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
665     if (!formDelegate) {
666         (core(m_webFrame.get())->loader()->*function)(PolicyUse);
667         return;
668     }
669
670     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:formState->values().size()];
671     HashMap<String, String>::const_iterator end = formState->values().end();
672     for (HashMap<String, String>::const_iterator it = formState->values().begin(); it != end; ++it)
673         [dictionary setObject:it->second forKey:it->first];
674
675     [formDelegate frame:m_webFrame.get()
676             sourceFrame:kit(formState->sourceFrame())
677          willSubmitForm:kit(formState->form())
678              withValues:dictionary
679      submissionListener:setUpPolicyListener(function).get()];
680
681     [dictionary release];
682 }
683
684 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader)
685 {
686     if ([WebScriptDebugServer listenerCount])
687         [[WebScriptDebugServer sharedScriptDebugServer] webView:getWebView(m_webFrame.get())
688             didLoadMainResourceForDataSource:dataSource(loader)];
689 }
690
691 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
692 {
693     [dataSource(loader) _revertToProvisionalState];
694 }
695
696 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
697 {
698     [dataSource(loader) _setMainDocumentError:error];
699 }
700
701 void WebFrameLoaderClient::clearUnarchivingState(DocumentLoader* loader)
702 {
703     [dataSource(loader) _clearUnarchivingState];
704 }
705
706 void WebFrameLoaderClient::willChangeEstimatedProgress()
707 {
708     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey];
709 }
710
711 void WebFrameLoaderClient::didChangeEstimatedProgress()
712 {
713     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey];
714 }
715
716 void WebFrameLoaderClient::postProgressStartedNotification()
717 {
718     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())];
719 }
720
721 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
722 {
723     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())];
724 }
725
726 void WebFrameLoaderClient::postProgressFinishedNotification()
727 {
728     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())];
729 }
730
731 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
732 {
733     [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
734 }
735
736 void WebFrameLoaderClient::startDownload(const ResourceRequest& request)
737 {
738     // FIXME: Should download full request.
739     [getWebView(m_webFrame.get()) _downloadURL:request.url().getNSURL()];
740 }
741
742 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
743 {
744     // FIXME: Should do this only in main frame case, right?
745     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
746 }
747
748 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
749 {
750     // FIXME: Should do this only in main frame case, right?
751     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
752 }
753
754 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
755 {
756     NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
757     [dataSource(loader) _receivedData:nsData];
758     [nsData release];
759 }
760
761 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
762 {
763     [dataSource(loader) _finishedLoading];
764 }
765
766 void WebFrameLoaderClient::finalSetupForReplace(DocumentLoader* loader)
767 {
768     [dataSource(loader) _clearUnarchivingState];
769 }
770
771 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
772 // Once that task is complete, this will go away
773 void WebFrameLoaderClient::updateGlobalHistoryForStandardLoad(const KURL& url)
774 {
775     NSURL *nsurl = url.getNSURL();
776     WebHistoryItem *entry = [[WebHistory optionalSharedHistory] addItemForURL:nsurl];
777     String pageTitle = core(m_webFrame.get())->loader()->documentLoader()->title();
778     if (pageTitle.length())
779         [entry setTitle:pageTitle];
780 }
781  
782 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
783 // Once that task is complete, this will go away
784 void WebFrameLoaderClient::updateGlobalHistoryForReload(const KURL& url)
785 {
786     WebHistory *sharedHistory = [WebHistory optionalSharedHistory];
787     WebHistoryItem *item = [sharedHistory itemForURL:url.getNSURL()];
788     if (item)
789         [sharedHistory setLastVisitedTimeInterval:[NSDate timeIntervalSinceReferenceDate] forItem:item];
790 }
791
792 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
793 {
794     WebView* view = getWebView(m_webFrame.get());
795     WebHistoryItem *webItem = kit(item);
796     
797     return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem];
798 }
799
800 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
801 {
802     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url().getNSURL()];
803 }
804     
805 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
806 {
807     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url().getNSURL()];
808 }
809
810 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
811 {
812     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url().getNSURL()];
813 }
814
815 ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
816 {
817     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url().getNSURL()];
818 }
819
820 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
821 {
822     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url().getNSURL()];
823 }
824
825 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
826 {
827     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url().getNSURL()];    
828 }
829
830 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
831 {
832     // FIXME: Needs to check domain.
833     // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
834     // loading plugin content twice.  See <rdar://problem/4258008>
835     return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad;
836 }
837
838 void WebFrameLoaderClient::setDefersLoading(bool defers)
839 {
840     if (!defers)
841         deliverArchivedResourcesAfterDelay();
842 }
843
844 bool WebFrameLoaderClient::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
845 {
846     if (request.url() != originalURL)
847         return false;
848     if (!canUseArchivedResource(request.nsURLRequest()))
849         return false;
850     WebResource *resource = [dataSource(core(m_webFrame.get())->loader()->activeDocumentLoader()) _archivedSubresourceForURL:originalURL.getNSURL()];
851     if (!resource)
852         return false;
853     if (!canUseArchivedResource([resource _response]))
854         return false;
855     m_pendingArchivedResources.set(loader, resource);
856     // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
857     deliverArchivedResourcesAfterDelay();
858     return true;
859 }
860
861 bool WebFrameLoaderClient::isArchiveLoadPending(ResourceLoader* loader) const
862 {
863     return m_pendingArchivedResources.contains(loader);
864 }
865
866 void WebFrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader* loader)
867 {
868     if (m_pendingArchivedResources.isEmpty())
869         return;
870     m_pendingArchivedResources.remove(loader);
871     if (m_pendingArchivedResources.isEmpty())
872         m_archivedResourcesDeliveryTimer.stop();
873 }
874
875 void WebFrameLoaderClient::clearArchivedResources()
876 {
877     m_pendingArchivedResources.clear();
878     m_archivedResourcesDeliveryTimer.stop();
879 }
880
881 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
882 {
883     return [WebView _canHandleRequest:request.nsURLRequest()];
884 }
885
886 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
887 {
888     return [WebView canShowMIMEType:MIMEType];
889 }
890
891 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
892 {
893     return [WebView _representationExistsForURLScheme:URLScheme];
894 }
895
896 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
897 {
898     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
899 }
900
901 void WebFrameLoaderClient::frameLoadCompleted()
902 {
903     // Note: Can be called multiple times.
904     // Even if already complete, we might have set a previous item on a frame that
905     // didn't do any data loading on the past transaction. Make sure to clear these out.
906     NSScrollView *sv = [m_webFrame->_private->webFrameView _scrollView];
907     if ([getWebView(m_webFrame.get()) drawsBackground])
908         [sv setDrawsBackground:YES];
909     core(m_webFrame.get())->loader()->setPreviousHistoryItem(0);
910 }
911
912
913 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item)
914 {
915     if (!item)
916         return;
917     
918     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
919
920     // we might already be detached when this is called from detachFromParent, in which
921     // case we don't want to override real data earlier gathered with (0,0)
922     if ([docView superview] && [docView conformsToProtocol:@protocol(_WebDocumentViewState)])
923         item->setViewState([(id <_WebDocumentViewState>)docView viewState]);
924 }
925
926 void WebFrameLoaderClient::restoreViewState()
927 {
928     HistoryItem* currentItem = core(m_webFrame.get())->loader()->currentHistoryItem();
929     ASSERT(currentItem);
930
931     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
932     // One counterexample is <rdar://problem/4917290>
933     // For now, to cover this issue in release builds, there is no technical harm to returning
934     // early and from a user standpoint - as in the above radar - the previous page load failed 
935     // so there *is* no scroll state to restore!
936     if (!currentItem)
937         return;
938     
939     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
940     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
941         id state = currentItem->viewState();
942         if (state) {
943             [(id <_WebDocumentViewState>)docView setViewState:state];
944         }
945     }
946 }
947
948 void WebFrameLoaderClient::provisionalLoadStarted()
949 {    
950     // FIXME: This is OK as long as no one resizes the window,
951     // but in the case where someone does, it means garbage outside
952     // the occupied part of the scroll view.
953     [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO];
954 }
955
956 void WebFrameLoaderClient::didFinishLoad()
957 {
958     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];    
959 }
960
961 void WebFrameLoaderClient::prepareForDataSourceReplacement()
962 {
963     if (![m_webFrame.get() _dataSource]) {
964         ASSERT(!core(m_webFrame.get())->tree()->childCount());
965         return;
966     }
967     
968     // Make sure that any work that is triggered by resigning first reponder can get done.
969     // The main example where this came up is the textDidEndEditing that is sent to the
970     // FormsDelegate (3223413).  We need to do this before _detachChildren, since that will
971     // remove the views as a side-effect of freeing the bridge, at which point we can't
972     // post the FormDelegate messages.
973     //
974     // Note that this can also take FirstResponder away from a child of our frameView that
975     // is not in a child frame's view.  This is OK because we are in the process
976     // of loading new content, which will blow away all editors in this top frame, and if
977     // a non-editor is firstReponder it will not be affected by endEditingFor:.
978     // Potentially one day someone could write a DocView whose editors were not all
979     // replaced by loading new content, but that does not apply currently.
980     NSView *frameView = m_webFrame->_private->webFrameView;
981     NSWindow *window = [frameView window];
982     NSResponder *firstResp = [window firstResponder];
983     if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
984         [window endEditingFor:firstResp];
985 }
986
987 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
988 {
989     RefPtr<WebDocumentLoaderMac> loader = new WebDocumentLoaderMac(request, substituteData);
990
991     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
992     loader->setDataSource(dataSource, getWebView(m_webFrame.get()));
993     [dataSource release];
994
995     return loader.release();
996 }
997
998 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
999 // Once that task is complete, this will go away
1000 void WebFrameLoaderClient::setTitle(const String& title, const KURL& URL)
1001 {
1002     NSURL* nsURL = canonicalURL(URL.getNSURL());
1003     if(!nsURL)
1004         return;
1005     NSString *titleNSString = title;
1006     [[[WebHistory optionalSharedHistory] itemForURL:nsURL] setTitle:titleNSString];
1007 }
1008
1009 // The following 2 functions are copied from [NSHTTPURLProtocol _cachedResponsePassesValidityChecks] and modified for our needs.
1010 // FIXME: It would be nice to eventually to share this logic somehow.
1011 bool WebFrameLoaderClient::canUseArchivedResource(NSURLRequest *request) const
1012 {
1013     NSURLRequestCachePolicy policy = [request cachePolicy];
1014     if (policy == NSURLRequestReturnCacheDataElseLoad)
1015         return true;
1016     if (policy == NSURLRequestReturnCacheDataDontLoad)
1017         return true;
1018     if ([request valueForHTTPHeaderField:@"must-revalidate"] != nil)
1019         return false;
1020     if ([request valueForHTTPHeaderField:@"proxy-revalidate"] != nil)
1021         return false;
1022     if ([request valueForHTTPHeaderField:@"If-Modified-Since"] != nil)
1023         return false;
1024     if ([request valueForHTTPHeaderField:@"Cache-Control"] != nil)
1025         return false;
1026     if ([@"POST" _webkit_isCaseInsensitiveEqualToString:[request HTTPMethod]])
1027         return false;
1028     return true;
1029 }
1030
1031 bool WebFrameLoaderClient::canUseArchivedResource(NSURLResponse *response) const
1032 {
1033     if (WKGetNSURLResponseMustRevalidate(response))
1034         return false;
1035     if (WKGetNSURLResponseCalculatedExpiration(response) - CFAbsoluteTimeGetCurrent() < 1)
1036         return false;
1037     return true;
1038 }
1039
1040 void WebFrameLoaderClient::deliverArchivedResourcesAfterDelay() const
1041 {
1042     if (m_pendingArchivedResources.isEmpty())
1043         return;
1044     if (core(m_webFrame.get())->page()->defersLoading())
1045         return;
1046     if (!m_archivedResourcesDeliveryTimer.isActive())
1047         m_archivedResourcesDeliveryTimer.startOneShot(0);
1048 }
1049
1050 void WebFrameLoaderClient::deliverArchivedResources(Timer<WebFrameLoaderClient>*)
1051 {
1052     if (m_pendingArchivedResources.isEmpty())
1053         return;
1054     if (core(m_webFrame.get())->page()->defersLoading())
1055         return;
1056
1057     const ResourceMap copy = m_pendingArchivedResources;
1058     m_pendingArchivedResources.clear();
1059
1060     ResourceMap::const_iterator end = copy.end();
1061     for (ResourceMap::const_iterator it = copy.begin(); it != end; ++it) {
1062         RefPtr<ResourceLoader> loader = it->first;
1063         WebResource *resource = it->second.get();
1064         NSData *data = [[resource data] retain];
1065         loader->didReceiveResponse([resource _response]);
1066         loader->didReceiveData((const char*)[data bytes], [data length], [data length], true);
1067         [data release];
1068         loader->didFinishLoading();
1069     }
1070 }
1071
1072 void WebFrameLoaderClient::saveDocumentViewToCachedPage(CachedPage* cachedPage)
1073 {
1074     cachedPage->setDocumentView([m_webFrame->_private->webFrameView documentView]);
1075 }
1076
1077 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
1078 {
1079     ASSERT(!m_policyListener);
1080     ASSERT(!m_policyFunction);
1081
1082     [m_policyListener.get() invalidate];
1083
1084     WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())];
1085     m_policyListener = listener;
1086     [listener release];
1087     m_policyFunction = function;
1088
1089     return listener;
1090 }
1091
1092 void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action)
1093 {
1094     ASSERT(m_policyListener);
1095     ASSERT(m_policyFunction);
1096
1097     FramePolicyFunction function = m_policyFunction;
1098
1099     m_policyListener = nil;
1100     m_policyFunction = 0;
1101
1102     (core(m_webFrame.get())->loader()->*function)(action);
1103 }
1104
1105 String WebFrameLoaderClient::userAgent(const KURL& url)
1106 {
1107     return [getWebView(m_webFrame.get()) _userAgentForURL:url];
1108 }
1109
1110 static const MouseEvent* findMouseEvent(const Event* event)
1111 {
1112     for (const Event* e = event; e; e = e->underlyingEvent())
1113         if (e->isMouseEvent())
1114             return static_cast<const MouseEvent*>(e);
1115     return 0;
1116 }
1117
1118 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action) const
1119 {
1120     unsigned modifierFlags = 0;
1121     const Event* event = action.event();
1122     if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) {
1123         if (keyStateEvent->ctrlKey())
1124             modifierFlags |= NSControlKeyMask;
1125         if (keyStateEvent->altKey())
1126             modifierFlags |= NSAlternateKeyMask;
1127         if (keyStateEvent->shiftKey())
1128             modifierFlags |= NSShiftKeyMask;
1129         if (keyStateEvent->metaKey())
1130             modifierFlags |= NSCommandKeyMask;
1131     }
1132     if (const MouseEvent* mouseEvent = findMouseEvent(event)) {
1133         IntPoint point(mouseEvent->clientX(), mouseEvent->clientY());
1134         WebElementDictionary *element = [[WebElementDictionary alloc]
1135             initWithHitTestResult:core(m_webFrame.get())->eventHandler()->hitTestResultAtPoint(point, false)];
1136         NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:
1137             [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1138             element, WebActionElementKey,
1139             [NSNumber numberWithInt:mouseEvent->button()], WebActionButtonKey,
1140             [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1141             action.URL().getNSURL(), WebActionOriginalURLKey,
1142             nil];
1143         [element release];
1144         return result;
1145     }
1146     return [NSDictionary dictionaryWithObjectsAndKeys:
1147         [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1148         [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1149         action.URL().getNSURL(), WebActionOriginalURLKey,
1150         nil];
1151 }
1152
1153 bool WebFrameLoaderClient::canCachePage() const
1154 {
1155     // We can only cache HTML pages right now
1156     return [[[m_webFrame.get() _dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]];
1157 }
1158
1159 Frame* WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1160                                          const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1161 {
1162     WebFrameBridge* bridge = m_webFrame->_private->bridge;
1163     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1164     
1165     return [bridge createChildFrameNamed:name
1166                    withURL:url.getNSURL()
1167                    referrer:referrer 
1168                    ownerElement:ownerElement
1169                    allowsScrolling:allowsScrolling
1170                    marginWidth:marginWidth
1171                    marginHeight:marginHeight];
1172
1173     END_BLOCK_OBJC_EXCEPTIONS;
1174     return 0;
1175 }
1176
1177 ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
1178 {
1179     WebFrameBridge* bridge = m_webFrame->_private->bridge;
1180     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1181     return (ObjectContentType)[bridge determineObjectFromMIMEType:mimeType URL:url.getNSURL()];
1182     END_BLOCK_OBJC_EXCEPTIONS;
1183     return ObjectContentNone;
1184 }
1185
1186 static NSArray* nsArray(const Vector<String>& vector)
1187 {
1188     unsigned len = vector.size();
1189     NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1190     for (unsigned x = 0; x < len; x++)
1191         [array addObject:vector[x]];
1192     return array;
1193 }
1194
1195 Widget* WebFrameLoaderClient::createPlugin(Element* element, const KURL& url, const Vector<String>& paramNames,
1196                                            const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1197 {
1198     WebFrameBridge* bridge = m_webFrame->_private->bridge;
1199
1200     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1201     return new Widget([bridge viewForPluginWithURL:url.getNSURL()
1202                               attributeNames:nsArray(paramNames)
1203                               attributeValues:nsArray(paramValues)
1204                               MIMEType:mimeType
1205                               DOMElement:[DOMElement _wrapElement:element]
1206                               loadManually:loadManually]);
1207     END_BLOCK_OBJC_EXCEPTIONS;
1208
1209     return 0;
1210 }
1211
1212 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
1213 {
1214     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1215     [m_webFrame->_private->bridge redirectDataToPlugin:pluginWidget->getView()];
1216     END_BLOCK_OBJC_EXCEPTIONS;
1217 }
1218
1219 WebCore::Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Element* element, const KURL& baseURL, 
1220                                                               const Vector<String>& paramNames, const Vector<String>& paramValues)
1221 {
1222     Widget* result = new Widget;
1223     
1224     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1225     WebFrameBridge* bridge = m_webFrame->_private->bridge;
1226     result->setView([bridge viewForJavaAppletWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1227                             attributeNames:nsArray(paramNames)
1228                             attributeValues:nsArray(paramValues)
1229                             baseURL:baseURL.getNSURL()
1230                             DOMElement:[DOMElement _wrapElement:element]]);    
1231     END_BLOCK_OBJC_EXCEPTIONS;
1232     
1233     return result;
1234 }
1235
1236 String WebFrameLoaderClient::overrideMediaType() const
1237 {
1238     NSString* overrideType = [m_webFrame->_private->bridge overrideMediaType];
1239     if (overrideType)
1240         return overrideType;
1241     return String();
1242 }
1243
1244 void WebFrameLoaderClient::windowObjectCleared() const
1245 {
1246     [m_webFrame->_private->bridge windowObjectCleared];
1247 }
1248
1249 @implementation WebFramePolicyListener
1250
1251 #ifndef BUILDING_ON_TIGER
1252 + (void)initialize
1253 {
1254     WebCoreObjCFinalizeOnMainThread(self);
1255 }
1256 #endif
1257
1258 - (id)initWithWebCoreFrame:(Frame*)frame
1259 {
1260     self = [self init];
1261     if (!self)
1262         return nil;
1263     frame->ref();
1264     m_frame = frame;
1265     return self;
1266 }
1267
1268 - (void)invalidate
1269 {
1270     if (m_frame) {
1271         m_frame->deref();
1272         m_frame = 0;
1273     }
1274 }
1275
1276 - (void)dealloc
1277 {
1278     if (m_frame)
1279         m_frame->deref();
1280     [super dealloc];
1281 }
1282
1283 - (void)finalize
1284 {
1285     ASSERT_MAIN_THREAD();
1286     if (m_frame)
1287         m_frame->deref();
1288     [super finalize];
1289 }
1290
1291 - (void)receivedPolicyDecision:(PolicyAction)action
1292 {
1293     RefPtr<Frame> frame = adoptRef(m_frame);
1294     m_frame = 0;
1295     if (frame)
1296         static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action);
1297 }
1298
1299 - (void)ignore
1300 {
1301     [self receivedPolicyDecision:PolicyIgnore];
1302 }
1303
1304 - (void)download
1305 {
1306     [self receivedPolicyDecision:PolicyDownload];
1307 }
1308
1309 - (void)use
1310 {
1311     [self receivedPolicyDecision:PolicyUse];
1312 }
1313
1314 - (void)continue
1315 {
1316     [self receivedPolicyDecision:PolicyUse];
1317 }
1318
1319
1320
1321 @end