WebCore:
[WebKit-https.git] / WebKit / mac / WebCoreSupport / WebFrameLoaderClient.mm
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple 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 "WebCachedPagePlatformData.h"
39 #import "WebChromeClient.h"
40 #import "WebDataSourceInternal.h"
41 #import "WebDocumentInternal.h"
42 #import "WebDocumentLoaderMac.h"
43 #import "WebDownloadInternal.h"
44 #import "WebDynamicScrollBarsViewInternal.h"
45 #import "WebElementDictionary.h"
46 #import "WebFormDelegate.h"
47 #import "WebFrameInternal.h"
48 #import "WebFrameLoadDelegate.h"
49 #import "WebFrameViewInternal.h"
50 #import "WebHTMLRepresentationPrivate.h"
51 #import "WebHTMLViewInternal.h"
52 #import "WebHistoryItemInternal.h"
53 #import "WebHistoryInternal.h"
54 #import "WebIconDatabaseInternal.h"
55 #import "WebJavaPlugIn.h"
56 #import "WebKitErrorsPrivate.h"
57 #import "WebKitLogging.h"
58 #import "WebKitNSStringExtras.h"
59 #import "WebNSURLExtras.h"
60 #import "WebNetscapePluginEmbeddedView.h"
61 #import "WebNetscapePluginPackage.h"
62 #import "WebNullPluginView.h"
63 #import "WebPanelAuthenticationHandler.h"
64 #import "WebPluginController.h"
65 #import "WebPluginPackage.h"
66 #import "WebPluginViewFactoryPrivate.h"
67 #import "WebPolicyDelegate.h"
68 #import "WebPolicyDelegatePrivate.h"
69 #import "WebPreferences.h"
70 #import "WebResourceLoadDelegate.h"
71 #import "WebResourcePrivate.h"
72 #import "WebScriptDebugServerPrivate.h"
73 #import "WebUIDelegate.h"
74 #import "WebUIDelegatePrivate.h"
75 #import "WebViewInternal.h"
76 #import <WebKitSystemInterface.h>
77 #import <WebCore/AuthenticationMac.h>
78 #import <WebCore/BlockExceptions.h>
79 #import <WebCore/CachedPage.h>
80 #import <WebCore/Chrome.h>
81 #import <WebCore/Document.h>
82 #import <WebCore/DocumentLoader.h>
83 #import <WebCore/EventHandler.h>
84 #import <WebCore/FormState.h>
85 #import <WebCore/Frame.h>
86 #import <WebCore/FrameLoader.h>
87 #import <WebCore/FrameLoaderTypes.h>
88 #import <WebCore/FrameTree.h>
89 #import <WebCore/FrameView.h>
90 #import <WebCore/HTMLFormElement.h>
91 #import <WebCore/HistoryItem.h>
92 #import <WebCore/HitTestResult.h>
93 #import <WebCore/IconDatabase.h>
94 #import <WebCore/LoaderNSURLExtras.h>
95 #import <WebCore/MIMETypeRegistry.h>
96 #import <WebCore/MouseEvent.h>
97 #import <WebCore/Page.h>
98 #import <WebCore/PlatformString.h>
99 #import <WebCore/ResourceError.h>
100 #import <WebCore/ResourceHandle.h>
101 #import <WebCore/ResourceLoader.h>
102 #import <WebCore/ResourceRequest.h>
103 #import <WebCore/SharedBuffer.h>
104 #import <WebCore/WebCoreObjCExtras.h>
105 #import <WebCore/Widget.h>
106 #import <WebKit/DOMElement.h>
107 #import <WebKit/DOMHTMLFormElement.h>
108 #import <wtf/PassRefPtr.h>
109
110 using namespace WebCore;
111
112 @interface NSView (WebJavaPluginDetails)
113 - (jobject)pollForAppletInWindow:(NSWindow *)window;
114 @end
115
116 // Needed for <rdar://problem/5121850> 
117 @interface NSURLDownload (WebNSURLDownloadDetails)
118 - (void)_setOriginatingURL:(NSURL *)originatingURL;
119 @end
120
121 // For backwards compatibility with older WebKit plug-ins.
122 NSString *WebPluginBaseURLKey = @"WebPluginBaseURL";
123 NSString *WebPluginAttributesKey = @"WebPluginAttributes";
124 NSString *WebPluginContainerKey = @"WebPluginContainer";
125
126 @interface WebFramePolicyListener : NSObject <WebPolicyDecisionListener, WebFormSubmissionListener> {
127     Frame* m_frame;
128 }
129 - (id)initWithWebCoreFrame:(Frame*)frame;
130 - (void)invalidate;
131 @end
132
133 static inline WebDataSource *dataSource(DocumentLoader* loader)
134 {
135     return loader ? static_cast<WebDocumentLoaderMac*>(loader)->dataSource() : nil;
136 }
137
138 WebFrameLoaderClient::WebFrameLoaderClient(WebFrame *webFrame)
139     : m_webFrame(webFrame)
140     , m_policyFunction(0)
141     , m_archivedResourcesDeliveryTimer(this, &WebFrameLoaderClient::deliverArchivedResources)
142 {
143 }
144
145 void WebFrameLoaderClient::frameLoaderDestroyed()
146 {
147     delete this;
148 }
149
150 bool WebFrameLoaderClient::hasWebView() const
151 {
152     return [m_webFrame.get() webView] != nil;
153 }
154
155 bool WebFrameLoaderClient::hasFrameView() const
156 {
157     return m_webFrame->_private->webFrameView != nil;
158 }
159
160 void WebFrameLoaderClient::makeRepresentation(DocumentLoader* loader)
161 {
162     [dataSource(loader) _makeRepresentation];
163 }
164
165 bool WebFrameLoaderClient::hasHTMLView() const
166 {
167     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
168     return [view isKindOfClass:[WebHTMLView class]];
169 }
170
171 void WebFrameLoaderClient::forceLayout()
172 {
173     NSView <WebDocumentView> *view = [m_webFrame->_private->webFrameView documentView];
174     if ([view isKindOfClass:[WebHTMLView class]])
175         [(WebHTMLView *)view setNeedsToApplyStyles:YES];
176     [view setNeedsLayout:YES];
177     [view layout];
178 }
179
180 void WebFrameLoaderClient::forceLayoutForNonHTML()
181 {
182     WebFrameView *thisView = m_webFrame->_private->webFrameView;
183     NSView <WebDocumentView> *thisDocumentView = [thisView documentView];
184     ASSERT(thisDocumentView != nil);
185     
186     // Tell the just loaded document to layout.  This may be necessary
187     // for non-html content that needs a layout message.
188     if (!([[m_webFrame.get() _dataSource] _isDocumentHTML])) {
189         [thisDocumentView setNeedsLayout:YES];
190         [thisDocumentView layout];
191         [thisDocumentView setNeedsDisplay:YES];
192     }
193 }
194
195 void WebFrameLoaderClient::setCopiesOnScroll()
196 {
197     [[[m_webFrame->_private->webFrameView _scrollView] contentView] setCopiesOnScroll:YES];
198 }
199
200 void WebFrameLoaderClient::detachedFromParent2()
201 {
202     [m_webFrame->_private->webFrameView _setWebFrame:nil]; // needed for now to be compatible w/ old behavior
203 }
204
205 void WebFrameLoaderClient::detachedFromParent3()
206 {
207     [m_webFrame->_private->webFrameView release];
208     m_webFrame->_private->webFrameView = nil;
209 }
210
211 void WebFrameLoaderClient::detachedFromParent4()
212 {
213 }
214
215 void WebFrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest& initialRequest, const ResourceResponse& response)
216 {
217     id proxy = handle->releaseProxy();
218     ASSERT(proxy);
219     
220     WebView *webView = getWebView(m_webFrame.get());
221     WebDownload *download = [WebDownload _downloadWithLoadingConnection:handle->connection()
222                                                                 request:request.nsURLRequest()
223                                                                response:response.nsURLResponse()
224                                                                delegate:[webView downloadDelegate]
225                                                                   proxy:proxy];
226     
227     setOriginalURLForDownload(download, initialRequest);    
228 }
229
230 void WebFrameLoaderClient::setOriginalURLForDownload(WebDownload *download, const ResourceRequest& initialRequest) const
231 {
232     NSURLRequest *initialURLRequest = initialRequest.nsURLRequest();
233     NSURL *originalURL = nil;
234     
235     // If there was no referrer, don't traverse the back/forward history
236     // since this download was initiated directly. <rdar://problem/5294691>
237     if ([initialURLRequest valueForHTTPHeaderField:@"Referer"]) {
238         // find the first item in the history that was originated by the user
239         WebView *webView = getWebView(m_webFrame.get());
240         WebBackForwardList *history = [webView backForwardList];
241         int backListCount = [history backListCount];
242         for (int backIndex = 0; backIndex <= backListCount && !originalURL; backIndex++) {
243             // FIXME: At one point we had code here to check a "was user gesture" flag.
244             // Do we need to restore that logic?
245             originalURL = [[history itemAtIndex:-backIndex] URL];
246         }
247     }
248
249     if (!originalURL)
250         originalURL = [initialURLRequest URL];
251
252     if ([download respondsToSelector:@selector(_setOriginatingURL:)]) {
253         NSString *scheme = [originalURL scheme];
254         NSString *host = [originalURL host];
255         if (scheme && host && [scheme length] && [host length]) {
256             NSNumber *port = [originalURL port];
257             if (port && [port intValue] < 0)
258                 port = nil;
259             NSString *hostOnlyURLString;
260             if (port)
261                 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@:%d", scheme, host, [port intValue]];
262             else
263                 hostOnlyURLString = [[NSString alloc] initWithFormat:@"%@://%@", scheme, host];
264             NSURL *hostOnlyURL = [[NSURL alloc] initWithString:hostOnlyURLString];
265             [hostOnlyURLString release];
266             [download _setOriginatingURL:hostOnlyURL];
267             [hostOnlyURL release];
268         }
269     }
270 }
271
272 bool WebFrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse& response, int length)
273 {
274     WebView *webView = getWebView(m_webFrame.get());
275     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
276     if (!implementations->didLoadResourceFromMemoryCacheFunc)
277         return false;
278
279     CallResourceLoadDelegate(implementations->didLoadResourceFromMemoryCacheFunc, webView, @selector(webView:didLoadResourceFromMemoryCache:response:length:fromDataSource:), request.nsURLRequest(), response.nsURLResponse(), length, dataSource(loader));
280     return true;
281 }
282
283 void WebFrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
284 {
285     WebView *webView = getWebView(m_webFrame.get());
286     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
287
288     id object = nil;
289     BOOL shouldRelease = NO;
290     if (implementations->identifierForRequestFunc)
291         object = CallResourceLoadDelegate(implementations->identifierForRequestFunc, webView, @selector(webView:identifierForInitialRequest:fromDataSource:), request.nsURLRequest(), dataSource(loader));
292     else {
293         object = [[NSObject alloc] init];
294         shouldRelease = YES;
295     }
296
297     [webView _addObject:object forIdentifier:identifier];
298
299     if (shouldRelease)
300         [object release];
301 }
302
303 void WebFrameLoaderClient::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
304 {
305     WebView *webView = getWebView(m_webFrame.get());
306     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
307
308     if (redirectResponse.isNull())
309         static_cast<WebDocumentLoaderMac*>(loader)->increaseLoadCount(identifier);
310
311     if (implementations->willSendRequestFunc)
312         request = (NSURLRequest *)CallResourceLoadDelegate(implementations->willSendRequestFunc, webView, @selector(webView:resource:willSendRequest:redirectResponse:fromDataSource:), [webView _objectForIdentifier:identifier], request.nsURLRequest(), redirectResponse.nsURLResponse(), dataSource(loader));
313 }
314
315 void WebFrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge& challenge)
316 {
317     WebView *webView = getWebView(m_webFrame.get());
318     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
319
320     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
321
322     if (implementations->didReceiveAuthenticationChallengeFunc) {
323         if (id resource = [webView _objectForIdentifier:identifier]) {
324             CallResourceLoadDelegate(implementations->didReceiveAuthenticationChallengeFunc, webView, @selector(webView:resource:didReceiveAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
325             return;
326         }
327     }
328
329     NSWindow *window = [webView hostWindow] ? [webView hostWindow] : [webView window];
330     [[WebPanelAuthenticationHandler sharedHandler] startAuthentication:webChallenge window:window];
331 }
332
333 void WebFrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader* loader, unsigned long identifier, const AuthenticationChallenge&challenge)
334 {
335     WebView *webView = getWebView(m_webFrame.get());
336     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
337     NSURLAuthenticationChallenge *webChallenge = mac(challenge);
338
339     if (implementations->didCancelAuthenticationChallengeFunc) {
340         if (id resource = [webView _objectForIdentifier:identifier]) {
341             CallResourceLoadDelegate(implementations->didCancelAuthenticationChallengeFunc, webView, @selector(webView:resource:didCancelAuthenticationChallenge:fromDataSource:), resource, webChallenge, dataSource(loader));
342             return;
343         }
344     }
345
346     [(WebPanelAuthenticationHandler *)[WebPanelAuthenticationHandler sharedHandler] cancelAuthentication:webChallenge];
347 }
348
349 void WebFrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
350 {
351     WebView *webView = getWebView(m_webFrame.get());
352     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
353     if (implementations->didReceiveResponseFunc) {
354         if (id resource = [webView _objectForIdentifier:identifier])
355             CallResourceLoadDelegate(implementations->didReceiveResponseFunc, webView, @selector(webView:resource:didReceiveResponse:fromDataSource:), resource, response.nsURLResponse(), dataSource(loader));
356     }
357 }
358
359 NSCachedURLResponse* WebFrameLoaderClient::willCacheResponse(DocumentLoader* loader, unsigned long identifier, NSCachedURLResponse* response) const
360 {
361     WebView *webView = getWebView(m_webFrame.get());
362     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
363
364     if (implementations->willCacheResponseFunc) {
365         if (id resource = [webView _objectForIdentifier:identifier])
366             return CallResourceLoadDelegate(implementations->willCacheResponseFunc, webView, @selector(webView:resource:willCacheResponse:fromDataSource:), resource, response, dataSource(loader));
367     }
368
369     return response;
370 }
371
372 void WebFrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int lengthReceived)
373 {
374     WebView *webView = getWebView(m_webFrame.get());
375     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
376     if (implementations->didReceiveContentLengthFunc) {
377         if (id resource = [webView _objectForIdentifier:identifier])
378             CallResourceLoadDelegate(implementations->didReceiveContentLengthFunc, webView, @selector(webView:resource:didReceiveContentLength:fromDataSource:), resource, (NSInteger)lengthReceived, dataSource(loader));
379     }
380 }
381
382 void WebFrameLoaderClient::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
383 {
384     WebView *webView = getWebView(m_webFrame.get());
385     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
386
387     if (implementations->didFinishLoadingFromDataSourceFunc) {
388         if (id resource = [webView _objectForIdentifier:identifier])
389             CallResourceLoadDelegate(implementations->didFinishLoadingFromDataSourceFunc, webView, @selector(webView:resource:didFinishLoadingFromDataSource:), resource, dataSource(loader));
390     }
391
392     [webView _removeObjectForIdentifier:identifier];
393
394     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
395 }
396
397 void WebFrameLoaderClient::dispatchDidFailLoading(DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
398 {
399     WebView *webView = getWebView(m_webFrame.get());
400     WebResourceDelegateImplementationCache* implementations = WebViewGetResourceLoadDelegateImplementations(webView);
401
402     if (implementations->didFailLoadingWithErrorFromDataSourceFunc) {
403         if (id resource = [webView _objectForIdentifier:identifier])
404             CallResourceLoadDelegate(implementations->didFailLoadingWithErrorFromDataSourceFunc, webView, @selector(webView:resource:didFailLoadingWithError:fromDataSource:), resource, (NSError *)error, dataSource(loader));
405     }
406
407     [webView _removeObjectForIdentifier:identifier];
408
409     static_cast<WebDocumentLoaderMac*>(loader)->decreaseLoadCount(identifier);
410 }
411
412 void WebFrameLoaderClient::dispatchDidHandleOnloadEvents()
413 {
414     WebView *webView = getWebView(m_webFrame.get());
415     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
416     if (implementations->didHandleOnloadEventsForFrameFunc)
417         CallFrameLoadDelegate(implementations->didHandleOnloadEventsForFrameFunc, webView, @selector(webView:didHandleOnloadEventsForFrame:), m_webFrame.get());
418 }
419
420 void WebFrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
421 {
422     WebView *webView = getWebView(m_webFrame.get());
423     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
424     if (implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc)
425         CallFrameLoadDelegate(implementations->didReceiveServerRedirectForProvisionalLoadForFrameFunc, webView, @selector(webView:didReceiveServerRedirectForProvisionalLoadForFrame:), m_webFrame.get());
426 }
427
428 void WebFrameLoaderClient::dispatchDidCancelClientRedirect()
429 {
430     WebView *webView = getWebView(m_webFrame.get());
431     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
432     if (implementations->didCancelClientRedirectForFrameFunc)
433         CallFrameLoadDelegate(implementations->didCancelClientRedirectForFrameFunc, webView, @selector(webView:didCancelClientRedirectForFrame:), m_webFrame.get());
434 }
435
436 void WebFrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double delay, double fireDate)
437 {
438     WebView *webView = getWebView(m_webFrame.get());
439     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
440     if (implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc) {
441         NSURL *cocoaURL = url;
442         CallFrameLoadDelegate(implementations->willPerformClientRedirectToURLDelayFireDateForFrameFunc, webView, @selector(webView:willPerformClientRedirectToURL:delay:fireDate:forFrame:), cocoaURL, delay, [NSDate dateWithTimeIntervalSince1970:fireDate], m_webFrame.get());
443     }
444 }
445
446 void WebFrameLoaderClient::dispatchDidChangeLocationWithinPage()
447 {
448     WebView *webView = getWebView(m_webFrame.get());
449     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
450     if (implementations->didChangeLocationWithinPageForFrameFunc)
451         CallFrameLoadDelegate(implementations->didChangeLocationWithinPageForFrameFunc, webView, @selector(webView:didChangeLocationWithinPageForFrame:), m_webFrame.get());
452 }
453
454 void WebFrameLoaderClient::dispatchWillClose()
455 {
456     WebView *webView = getWebView(m_webFrame.get());   
457     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
458     if (implementations->willCloseFrameFunc)
459         CallFrameLoadDelegate(implementations->willCloseFrameFunc, webView, @selector(webView:willCloseFrame:), m_webFrame.get());
460 }
461
462 void WebFrameLoaderClient::dispatchDidReceiveIcon()
463 {
464     ASSERT([m_webFrame.get() _isMainFrame]);
465     WebView *webView = getWebView(m_webFrame.get());   
466
467     [webView _dispatchDidReceiveIconFromWebFrame:m_webFrame.get()];
468 }
469
470 void WebFrameLoaderClient::dispatchDidStartProvisionalLoad()
471 {
472     WebView *webView = getWebView(m_webFrame.get());   
473     [webView _didStartProvisionalLoadForFrame:m_webFrame.get()];
474
475     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
476     if (implementations->didStartProvisionalLoadForFrameFunc)
477         CallFrameLoadDelegate(implementations->didStartProvisionalLoadForFrameFunc, webView, @selector(webView:didStartProvisionalLoadForFrame:), m_webFrame.get());
478 }
479
480 void WebFrameLoaderClient::dispatchDidReceiveTitle(const String& title)
481 {
482     WebView *webView = getWebView(m_webFrame.get());   
483     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
484     if (implementations->didReceiveTitleForFrameFunc)
485         CallFrameLoadDelegate(implementations->didReceiveTitleForFrameFunc, webView, @selector(webView:didReceiveTitle:forFrame:), (NSString *)title, m_webFrame.get());
486 }
487
488 void WebFrameLoaderClient::dispatchDidCommitLoad()
489 {
490     // Tell the client we've committed this URL.
491     ASSERT([m_webFrame->_private->webFrameView documentView] != nil);
492     
493     WebView *webView = getWebView(m_webFrame.get());   
494     [webView _didCommitLoadForFrame:m_webFrame.get()];
495
496     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
497     if (implementations->didCommitLoadForFrameFunc)
498         CallFrameLoadDelegate(implementations->didCommitLoadForFrameFunc, webView, @selector(webView:didCommitLoadForFrame:), m_webFrame.get());
499 }
500
501 void WebFrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
502 {
503     WebView *webView = getWebView(m_webFrame.get());   
504     [webView _didFailProvisionalLoadWithError:error forFrame:m_webFrame.get()];
505
506     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
507     if (implementations->didFailProvisionalLoadWithErrorForFrameFunc)
508         CallFrameLoadDelegate(implementations->didFailProvisionalLoadWithErrorForFrameFunc, webView, @selector(webView:didFailProvisionalLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
509
510     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
511 }
512
513 void WebFrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
514 {
515     WebView *webView = getWebView(m_webFrame.get());   
516     [webView _didFailLoadWithError:error forFrame:m_webFrame.get()];
517
518     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
519     if (implementations->didFailLoadWithErrorForFrameFunc)
520         CallFrameLoadDelegate(implementations->didFailLoadWithErrorForFrameFunc, webView, @selector(webView:didFailLoadWithError:forFrame:), (NSError *)error, m_webFrame.get());
521
522     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:error];
523 }
524
525 void WebFrameLoaderClient::dispatchDidFinishDocumentLoad()
526 {
527     WebView *webView = getWebView(m_webFrame.get());
528     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
529     if (implementations->didFinishDocumentLoadForFrameFunc)
530         CallFrameLoadDelegate(implementations->didFinishDocumentLoadForFrameFunc, webView, @selector(webView:didFinishDocumentLoadForFrame:), m_webFrame.get());
531 }
532
533 void WebFrameLoaderClient::dispatchDidFinishLoad()
534 {
535     WebView *webView = getWebView(m_webFrame.get());   
536     [webView _didFinishLoadForFrame:m_webFrame.get()];
537
538     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
539     if (implementations->didFinishLoadForFrameFunc)
540         CallFrameLoadDelegate(implementations->didFinishLoadForFrameFunc, webView, @selector(webView:didFinishLoadForFrame:), m_webFrame.get());
541
542     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];
543 }
544
545 void WebFrameLoaderClient::dispatchDidFirstLayout()
546 {
547     WebView *webView = getWebView(m_webFrame.get());
548     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
549     if (implementations->didFirstLayoutInFrameFunc)
550         CallFrameLoadDelegate(implementations->didFirstLayoutInFrameFunc, webView, @selector(webView:didFirstLayoutInFrame:), m_webFrame.get());
551 }
552
553 Frame* WebFrameLoaderClient::dispatchCreatePage()
554 {
555     WebView *currentWebView = getWebView(m_webFrame.get());
556     NSDictionary *features = [[NSDictionary alloc] init];
557     WebView *newWebView = [[currentWebView _UIDelegateForwarder] webView:currentWebView 
558                                                 createWebViewWithRequest:nil
559                                                           windowFeatures:features];
560     [features release];
561     return core([newWebView mainFrame]);
562 }
563
564 void WebFrameLoaderClient::dispatchShow()
565 {
566     WebView *webView = getWebView(m_webFrame.get());
567     [[webView _UIDelegateForwarder] webViewShow:webView];
568 }
569
570 void WebFrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction function,
571     const String& MIMEType, const ResourceRequest& request)
572 {
573     WebView *webView = getWebView(m_webFrame.get());
574
575     [[webView _policyDelegateForwarder] webView:webView
576                         decidePolicyForMIMEType:MIMEType
577                                         request:request.nsURLRequest()
578                                           frame:m_webFrame.get()
579                                decisionListener:setUpPolicyListener(function).get()];
580 }
581
582 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction function,
583     const NavigationAction& action, const ResourceRequest& request, const String& frameName)
584 {
585     WebView *webView = getWebView(m_webFrame.get());
586     [[webView _policyDelegateForwarder] webView:webView
587             decidePolicyForNewWindowAction:actionDictionary(action)
588                                    request:request.nsURLRequest()
589                               newFrameName:frameName
590                           decisionListener:setUpPolicyListener(function).get()];
591 }
592
593 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction function,
594     const NavigationAction& action, const ResourceRequest& request)
595 {
596     WebView *webView = getWebView(m_webFrame.get());
597     [[webView _policyDelegateForwarder] webView:webView
598                 decidePolicyForNavigationAction:actionDictionary(action)
599                                         request:request.nsURLRequest()
600                                           frame:m_webFrame.get()
601                                decisionListener:setUpPolicyListener(function).get()];
602 }
603
604 void WebFrameLoaderClient::cancelPolicyCheck()
605 {
606     [m_policyListener.get() invalidate];
607     m_policyListener = nil;
608     m_policyFunction = 0;
609 }
610
611 void WebFrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError& error)
612 {
613     WebView *webView = getWebView(m_webFrame.get());
614     [[webView _policyDelegateForwarder] webView:webView unableToImplementPolicyWithError:error frame:m_webFrame.get()];    
615 }
616
617 void WebFrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction function, PassRefPtr<FormState> formState)
618 {
619     id <WebFormDelegate> formDelegate = [getWebView(m_webFrame.get()) _formDelegate];
620     if (!formDelegate) {
621         (core(m_webFrame.get())->loader()->*function)(PolicyUse);
622         return;
623     }
624
625     NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] initWithCapacity:formState->values().size()];
626     HashMap<String, String>::const_iterator end = formState->values().end();
627     for (HashMap<String, String>::const_iterator it = formState->values().begin(); it != end; ++it)
628         [dictionary setObject:it->second forKey:it->first];
629
630     CallFormDelegate(getWebView(m_webFrame.get()), @selector(frame:sourceFrame:willSubmitForm:withValues:submissionListener:), m_webFrame.get(), kit(formState->sourceFrame()), kit(formState->form()), dictionary, setUpPolicyListener(function).get());
631
632     [dictionary release];
633 }
634
635 void WebFrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader* loader)
636 {
637     if ([WebScriptDebugServer listenerCount])
638         [[WebScriptDebugServer sharedScriptDebugServer] webView:getWebView(m_webFrame.get()) didLoadMainResourceForDataSource:dataSource(loader)];
639 }
640
641 void WebFrameLoaderClient::revertToProvisionalState(DocumentLoader* loader)
642 {
643     [dataSource(loader) _revertToProvisionalState];
644 }
645
646 void WebFrameLoaderClient::setMainDocumentError(DocumentLoader* loader, const ResourceError& error)
647 {
648     [dataSource(loader) _setMainDocumentError:error];
649 }
650
651 void WebFrameLoaderClient::clearUnarchivingState(DocumentLoader* loader)
652 {
653     [dataSource(loader) _clearUnarchivingState];
654 }
655
656 void WebFrameLoaderClient::willChangeEstimatedProgress()
657 {
658     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebEstimatedProgressKey];
659 }
660
661 void WebFrameLoaderClient::didChangeEstimatedProgress()
662 {
663     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebEstimatedProgressKey];
664 }
665
666 void WebFrameLoaderClient::postProgressStartedNotification()
667 {
668     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:getWebView(m_webFrame.get())];
669 }
670
671 void WebFrameLoaderClient::postProgressEstimateChangedNotification()
672 {
673     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:getWebView(m_webFrame.get())];
674 }
675
676 void WebFrameLoaderClient::postProgressFinishedNotification()
677 {
678     [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressFinishedNotification object:getWebView(m_webFrame.get())];
679 }
680
681 void WebFrameLoaderClient::setMainFrameDocumentReady(bool ready)
682 {
683     [getWebView(m_webFrame.get()) setMainFrameDocumentReady:ready];
684 }
685
686 void WebFrameLoaderClient::startDownload(const ResourceRequest& request)
687 {
688     // FIXME: Should download full request.
689     WebDownload *download = [getWebView(m_webFrame.get()) _downloadURL:request.url()];
690     
691     setOriginalURLForDownload(download, request);
692 }
693
694 void WebFrameLoaderClient::willChangeTitle(DocumentLoader* loader)
695 {
696     // FIXME: Should do this only in main frame case, right?
697     [getWebView(m_webFrame.get()) _willChangeValueForKey:_WebMainFrameTitleKey];
698 }
699
700 void WebFrameLoaderClient::didChangeTitle(DocumentLoader* loader)
701 {
702     // FIXME: Should do this only in main frame case, right?
703     [getWebView(m_webFrame.get()) _didChangeValueForKey:_WebMainFrameTitleKey];
704 }
705
706 void WebFrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
707 {
708     NSData *nsData = [[NSData alloc] initWithBytesNoCopy:(void*)data length:length freeWhenDone:NO];
709     [dataSource(loader) _receivedData:nsData];
710     [nsData release];
711 }
712
713 void WebFrameLoaderClient::finishedLoading(DocumentLoader* loader)
714 {
715     [dataSource(loader) _finishedLoading];
716 }
717
718 void WebFrameLoaderClient::finalSetupForReplace(DocumentLoader* loader)
719 {
720     [dataSource(loader) _clearUnarchivingState];
721 }
722
723 void WebFrameLoaderClient::updateGlobalHistory(const KURL& url)
724 {
725     NSURL *cocoaURL = url;
726     const String& pageTitle = core(m_webFrame.get())->loader()->documentLoader()->title();
727     [[WebHistory optionalSharedHistory] _addItemForURL:cocoaURL title:pageTitle];
728 }
729  
730 bool WebFrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
731 {
732     WebView* view = getWebView(m_webFrame.get());
733     WebHistoryItem *webItem = kit(item);
734     
735     return [[view _policyDelegateForwarder] webView:view shouldGoToHistoryItem:webItem];
736 }
737
738 ResourceError WebFrameLoaderClient::cancelledError(const ResourceRequest& request)
739 {
740     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled URL:request.url()];
741 }
742     
743 ResourceError WebFrameLoaderClient::blockedError(const ResourceRequest& request)
744 {
745     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotUseRestrictedPort URL:request.url()];
746 }
747
748 ResourceError WebFrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
749 {
750     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorCannotShowURL URL:request.url()];
751 }
752
753 ResourceError WebFrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
754 {
755     return [NSError _webKitErrorWithDomain:WebKitErrorDomain code:WebKitErrorFrameLoadInterruptedByPolicyChange URL:request.url()];
756 }
757
758 ResourceError WebFrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
759 {
760     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:WebKitErrorCannotShowMIMEType URL:response.url()];
761 }
762
763 ResourceError WebFrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
764 {
765     return [NSError _webKitErrorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist URL:response.url()];    
766 }
767
768 bool WebFrameLoaderClient::shouldFallBack(const ResourceError& error)
769 {
770     // FIXME: Needs to check domain.
771     // FIXME: WebKitErrorPlugInWillHandleLoad is a workaround for the cancel we do to prevent
772     // loading plugin content twice.  See <rdar://problem/4258008>
773     return error.errorCode() != NSURLErrorCancelled && error.errorCode() != WebKitErrorPlugInWillHandleLoad;
774 }
775
776 void WebFrameLoaderClient::setDefersLoading(bool defers)
777 {
778     if (!defers)
779         deliverArchivedResourcesAfterDelay();
780 }
781
782 bool WebFrameLoaderClient::willUseArchive(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL) const
783 {
784     if (request.url() != originalURL)
785         return false;
786
787     WebResource *resource = [dataSource(core(m_webFrame.get())->loader()->activeDocumentLoader()) _archivedSubresourceForURL:originalURL];
788     if (!resource)
789         return false;
790
791     m_pendingArchivedResources.set(loader, resource);
792     // Deliver the resource after a delay because callers don't expect to receive callbacks while calling this method.
793     deliverArchivedResourcesAfterDelay();
794
795     return true;
796 }
797
798 bool WebFrameLoaderClient::isArchiveLoadPending(ResourceLoader* loader) const
799 {
800     return m_pendingArchivedResources.contains(loader);
801 }
802
803 void WebFrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader* loader)
804 {
805     if (m_pendingArchivedResources.isEmpty())
806         return;
807     m_pendingArchivedResources.remove(loader);
808     if (m_pendingArchivedResources.isEmpty())
809         m_archivedResourcesDeliveryTimer.stop();
810 }
811
812 void WebFrameLoaderClient::clearArchivedResources()
813 {
814     m_pendingArchivedResources.clear();
815     m_archivedResourcesDeliveryTimer.stop();
816 }
817
818 bool WebFrameLoaderClient::canHandleRequest(const ResourceRequest& request) const
819 {
820     return [WebView _canHandleRequest:request.nsURLRequest()];
821 }
822
823 bool WebFrameLoaderClient::canShowMIMEType(const String& MIMEType) const
824 {
825     return [WebView canShowMIMEType:MIMEType];
826 }
827
828 bool WebFrameLoaderClient::representationExistsForURLScheme(const String& URLScheme) const
829 {
830     return [WebView _representationExistsForURLScheme:URLScheme];
831 }
832
833 String WebFrameLoaderClient::generatedMIMETypeForURLScheme(const String& URLScheme) const
834 {
835     return [WebView _generatedMIMETypeForURLScheme:URLScheme];
836 }
837
838 void WebFrameLoaderClient::frameLoadCompleted()
839 {
840     // Note: Can be called multiple times.
841     // Even if already complete, we might have set a previous item on a frame that
842     // didn't do any data loading on the past transaction. Make sure to clear these out.
843     NSScrollView *sv = [m_webFrame->_private->webFrameView _scrollView];
844     if ([getWebView(m_webFrame.get()) drawsBackground])
845         [sv setDrawsBackground:YES];
846     core(m_webFrame.get())->loader()->setPreviousHistoryItem(0);
847 }
848
849
850 void WebFrameLoaderClient::saveViewStateToItem(HistoryItem* item)
851 {
852     if (!item)
853         return;
854     
855     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
856
857     // we might already be detached when this is called from detachFromParent, in which
858     // case we don't want to override real data earlier gathered with (0,0)
859     if ([docView superview] && [docView conformsToProtocol:@protocol(_WebDocumentViewState)])
860         item->setViewState([(id <_WebDocumentViewState>)docView viewState]);
861 }
862
863 void WebFrameLoaderClient::restoreViewState()
864 {
865     HistoryItem* currentItem = core(m_webFrame.get())->loader()->currentHistoryItem();
866     ASSERT(currentItem);
867
868     // FIXME: As the ASSERT attests, it seems we should always have a currentItem here.
869     // One counterexample is <rdar://problem/4917290>
870     // For now, to cover this issue in release builds, there is no technical harm to returning
871     // early and from a user standpoint - as in the above radar - the previous page load failed 
872     // so there *is* no scroll state to restore!
873     if (!currentItem)
874         return;
875     
876     NSView <WebDocumentView> *docView = [m_webFrame->_private->webFrameView documentView];
877     if ([docView conformsToProtocol:@protocol(_WebDocumentViewState)]) {        
878         id state = currentItem->viewState();
879         if (state) {
880             [(id <_WebDocumentViewState>)docView setViewState:state];
881         }
882     }
883 }
884
885 void WebFrameLoaderClient::provisionalLoadStarted()
886 {    
887     // FIXME: This is OK as long as no one resizes the window,
888     // but in the case where someone does, it means garbage outside
889     // the occupied part of the scroll view.
890     [[m_webFrame->_private->webFrameView _scrollView] setDrawsBackground:NO];
891 }
892
893 void WebFrameLoaderClient::didFinishLoad()
894 {
895     [m_webFrame->_private->internalLoadDelegate webFrame:m_webFrame.get() didFinishLoadWithError:nil];    
896 }
897
898 void WebFrameLoaderClient::prepareForDataSourceReplacement()
899 {
900     if (![m_webFrame.get() _dataSource]) {
901         ASSERT(!core(m_webFrame.get())->tree()->childCount());
902         return;
903     }
904     
905     // Make sure that any work that is triggered by resigning first reponder can get done.
906     // The main example where this came up is the textDidEndEditing that is sent to the
907     // FormsDelegate (3223413). We need to do this before _detachChildren, since that will
908     // remove the views as a side-effect of freeing the frame, at which point we can't
909     // post the FormDelegate messages.
910     //
911     // Note that this can also take FirstResponder away from a child of our frameView that
912     // is not in a child frame's view.  This is OK because we are in the process
913     // of loading new content, which will blow away all editors in this top frame, and if
914     // a non-editor is firstReponder it will not be affected by endEditingFor:.
915     // Potentially one day someone could write a DocView whose editors were not all
916     // replaced by loading new content, but that does not apply currently.
917     NSView *frameView = m_webFrame->_private->webFrameView;
918     NSWindow *window = [frameView window];
919     NSResponder *firstResp = [window firstResponder];
920     if ([firstResp isKindOfClass:[NSView class]] && [(NSView *)firstResp isDescendantOf:frameView])
921         [window endEditingFor:firstResp];
922 }
923
924 PassRefPtr<DocumentLoader> WebFrameLoaderClient::createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData)
925 {
926     RefPtr<WebDocumentLoaderMac> loader = new WebDocumentLoaderMac(request, substituteData);
927
928     WebDataSource *dataSource = [[WebDataSource alloc] _initWithDocumentLoader:loader.get()];
929     loader->setDataSource(dataSource, getWebView(m_webFrame.get()));
930     [dataSource release];
931
932     return loader.release();
933 }
934
935 // FIXME: <rdar://problem/4880065> - Push Global History into WebCore
936 // Once that task is complete, this will go away
937 void WebFrameLoaderClient::setTitle(const String& title, const KURL& URL)
938 {
939     NSURL* nsURL = URL;
940     nsURL = [nsURL _webkit_canonicalize];
941     if(!nsURL)
942         return;
943     NSString *titleNSString = title;
944     [[[WebHistory optionalSharedHistory] itemForURL:nsURL] setTitle:titleNSString];
945 }
946
947 void WebFrameLoaderClient::deliverArchivedResourcesAfterDelay() const
948 {
949     if (m_pendingArchivedResources.isEmpty())
950         return;
951     if (core(m_webFrame.get())->page()->defersLoading())
952         return;
953     if (!m_archivedResourcesDeliveryTimer.isActive())
954         m_archivedResourcesDeliveryTimer.startOneShot(0);
955 }
956
957 void WebFrameLoaderClient::deliverArchivedResources(Timer<WebFrameLoaderClient>*)
958 {
959     if (m_pendingArchivedResources.isEmpty())
960         return;
961     if (core(m_webFrame.get())->page()->defersLoading())
962         return;
963
964     const ResourceMap copy = m_pendingArchivedResources;
965     m_pendingArchivedResources.clear();
966
967     ResourceMap::const_iterator end = copy.end();
968     for (ResourceMap::const_iterator it = copy.begin(); it != end; ++it) {
969         RefPtr<ResourceLoader> loader = it->first;
970         WebResource *resource = it->second.get();
971         NSData *data = [[resource data] retain];
972         loader->didReceiveResponse([resource _response]);
973         loader->didReceiveData((const char*)[data bytes], [data length], [data length], true);
974         [data release];
975         loader->didFinishLoading();
976     }
977 }
978
979 void WebFrameLoaderClient::savePlatformDataToCachedPage(CachedPage* cachedPage)
980 {
981     WebCachedPagePlatformData* webPlatformData = new WebCachedPagePlatformData([m_webFrame->_private->webFrameView documentView]);
982     cachedPage->setCachedPagePlatformData(webPlatformData);
983 }
984
985 void WebFrameLoaderClient::transitionToCommittedFromCachedPage(CachedPage* cachedPage)
986 {
987     WebCachedPagePlatformData* platformData = reinterpret_cast<WebCachedPagePlatformData*>(cachedPage->cachedPagePlatformData());
988     NSView <WebDocumentView> *cachedView = platformData->webDocumentView();
989     ASSERT(cachedView != nil);
990     ASSERT(cachedPage->documentLoader());
991     [cachedView setDataSource:dataSource(cachedPage->documentLoader())];
992     [m_webFrame->_private->webFrameView _setDocumentView:cachedView];
993 }
994
995 void WebFrameLoaderClient::transitionToCommittedForNewPage()
996 {
997     WebFrameView *v = m_webFrame->_private->webFrameView;
998     WebDataSource *ds = [m_webFrame.get() _dataSource];
999
1000     bool willProduceHTMLView = [[WebFrameView class] _viewClassForMIMEType:[ds _responseMIMEType]] == [WebHTMLView class];
1001     bool canSkipCreation = [m_webFrame.get() _frameLoader]->committingFirstRealLoad() && willProduceHTMLView;
1002     if (canSkipCreation) {
1003         [[v documentView] setDataSource:ds];
1004         return;
1005     }
1006
1007     // Don't suppress scrollbars before the view creation if we're making the view for a non-HTML view.
1008     if (!willProduceHTMLView)
1009         [[v _scrollView] setScrollBarsSuppressed:NO repaintOnUnsuppress:NO];
1010     
1011     NSView <WebDocumentView> *documentView = [v _makeDocumentViewForDataSource:ds];
1012     if (!documentView)
1013         return;
1014
1015     // FIXME: Could we skip some of this work for a top-level view that is not a WebHTMLView?
1016
1017     // If we own the view, delete the old one - otherwise the render m_frame will take care of deleting the view.
1018     Frame* coreFrame = core(m_webFrame.get());
1019     coreFrame->setView(0);
1020     FrameView* coreView = new FrameView(coreFrame);
1021     coreFrame->setView(coreView);
1022     coreView->deref(); // FIXME: Eliminate this crazy refcounting!
1023     int marginWidth = [v _marginWidth];
1024     if (marginWidth >= 0)
1025         coreView->setMarginWidth(marginWidth);
1026     int marginHeight = [v _marginHeight];
1027     if (marginHeight >= 0)
1028         coreView->setMarginHeight(marginHeight);
1029
1030     [m_webFrame.get() _updateBackground];
1031
1032     [v _install];
1033
1034     // Call setDataSource on the document view after it has been placed in the view hierarchy.
1035     // This what we for the top-level view, so should do this for views in subframes as well.
1036     [documentView setDataSource:ds];
1037 }
1038
1039 RetainPtr<WebFramePolicyListener> WebFrameLoaderClient::setUpPolicyListener(FramePolicyFunction function)
1040 {
1041     // FIXME: <rdar://5634381> We need to support multiple active policy listeners.
1042
1043     [m_policyListener.get() invalidate];
1044
1045     WebFramePolicyListener *listener = [[WebFramePolicyListener alloc] initWithWebCoreFrame:core(m_webFrame.get())];
1046     m_policyListener = listener;
1047     [listener release];
1048     m_policyFunction = function;
1049
1050     return listener;
1051 }
1052
1053 void WebFrameLoaderClient::receivedPolicyDecison(PolicyAction action)
1054 {
1055     ASSERT(m_policyListener);
1056     ASSERT(m_policyFunction);
1057
1058     FramePolicyFunction function = m_policyFunction;
1059
1060     m_policyListener = nil;
1061     m_policyFunction = 0;
1062
1063     (core(m_webFrame.get())->loader()->*function)(action);
1064 }
1065
1066 String WebFrameLoaderClient::userAgent(const KURL& url)
1067 {
1068     return [getWebView(m_webFrame.get()) _userAgentForURL:url];
1069 }
1070
1071 static const MouseEvent* findMouseEvent(const Event* event)
1072 {
1073     for (const Event* e = event; e; e = e->underlyingEvent())
1074         if (e->isMouseEvent())
1075             return static_cast<const MouseEvent*>(e);
1076     return 0;
1077 }
1078
1079 NSDictionary *WebFrameLoaderClient::actionDictionary(const NavigationAction& action) const
1080 {
1081     unsigned modifierFlags = 0;
1082     const Event* event = action.event();
1083     if (const UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event))) {
1084         if (keyStateEvent->ctrlKey())
1085             modifierFlags |= NSControlKeyMask;
1086         if (keyStateEvent->altKey())
1087             modifierFlags |= NSAlternateKeyMask;
1088         if (keyStateEvent->shiftKey())
1089             modifierFlags |= NSShiftKeyMask;
1090         if (keyStateEvent->metaKey())
1091             modifierFlags |= NSCommandKeyMask;
1092     }
1093     NSURL *originalURL = action.url();
1094     if (const MouseEvent* mouseEvent = findMouseEvent(event)) {
1095         IntPoint point(mouseEvent->pageX(), mouseEvent->pageY());
1096         WebElementDictionary *element = [[WebElementDictionary alloc]
1097             initWithHitTestResult:core(m_webFrame.get())->eventHandler()->hitTestResultAtPoint(point, false)];
1098         NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:
1099             [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1100             element, WebActionElementKey,
1101             [NSNumber numberWithInt:mouseEvent->button()], WebActionButtonKey,
1102             [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1103             originalURL, WebActionOriginalURLKey,
1104             nil];
1105         [element release];
1106         return result;
1107     }
1108     return [NSDictionary dictionaryWithObjectsAndKeys:
1109         [NSNumber numberWithInt:action.type()], WebActionNavigationTypeKey,
1110         [NSNumber numberWithInt:modifierFlags], WebActionModifierFlagsKey,
1111         originalURL, WebActionOriginalURLKey,
1112         nil];
1113 }
1114
1115 bool WebFrameLoaderClient::canCachePage() const
1116 {
1117     // We can only cache HTML pages right now
1118     return [[[m_webFrame.get() _dataSource] representation] isKindOfClass:[WebHTMLRepresentation class]];
1119 }
1120
1121 PassRefPtr<Frame> WebFrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
1122     const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
1123 {
1124     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1125     
1126     ASSERT(m_webFrame);
1127     
1128     WebFrameView *childView = [[WebFrameView alloc] init];
1129     [childView setAllowsScrolling:allowsScrolling];
1130     [childView _setMarginWidth:marginWidth];
1131     [childView _setMarginHeight:marginHeight];
1132
1133     RefPtr<Frame> newCoreFrame = [WebFrame _createSubframeWithOwnerElement:ownerElement frameName:name frameView:childView];
1134
1135     [childView release];
1136
1137     if (!newCoreFrame)
1138         return 0;
1139
1140     WebFrame *newFrame = kit(newCoreFrame.get());
1141
1142     [m_webFrame.get() _addChild:newFrame];    
1143     [m_webFrame.get() _loadURL:url referrer:referrer intoChild:newFrame];
1144
1145     // The frame's onload handler may have removed it from the document.
1146     if (!newCoreFrame->tree()->parent())
1147         return 0;
1148
1149     return newCoreFrame.release();
1150
1151     END_BLOCK_OBJC_EXCEPTIONS;
1152
1153     return 0;
1154 }
1155
1156 ObjectContentType WebFrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
1157 {
1158     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1159
1160     // This is a quirk that ensures Tiger Mail's WebKit plug-in will load during layout
1161     // and not attach time. (5520541)
1162     static BOOL isTigerMail = WKAppVersionCheckLessThan(@"com.apple.mail", -1, 3.0);
1163     if (isTigerMail && mimeType == "application/x-apple-msg-attachment")
1164         return ObjectContentNetscapePlugin;
1165
1166     String type = mimeType;
1167
1168     if (type.isEmpty()) {
1169         // Try to guess the MIME type based off the extension.
1170         NSURL *URL = url;
1171         NSString *extension = [[URL path] pathExtension];
1172         if ([extension length] > 0) {
1173             type = WKGetMIMETypeForExtension(extension);
1174             if (type.isEmpty()) {
1175                 // If no MIME type is specified, use a plug-in if we have one that can handle the extension.
1176                 if (WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForExtension:extension]) {
1177                     if ([package isKindOfClass:[WebPluginPackage class]]) 
1178                         return ObjectContentOtherPlugin;
1179 #if ENABLE(NETSCAPE_PLUGIN_API)
1180                     else {
1181                         ASSERT([package isKindOfClass:[WebNetscapePluginPackage class]]);
1182                         return ObjectContentNetscapePlugin;
1183                     }
1184 #endif
1185                 }
1186             }
1187         }
1188     }
1189
1190     if (type.isEmpty())
1191         return ObjectContentFrame; // Go ahead and hope that we can display the content.
1192
1193     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
1194         return ObjectContentImage;
1195
1196     WebBasePluginPackage *package = [getWebView(m_webFrame.get()) _pluginForMIMEType:type];
1197     if (package) {
1198 #if ENABLE(NETSCAPE_PLUGIN_API)
1199         if ([package isKindOfClass:[WebNetscapePluginPackage class]])
1200             return ObjectContentNetscapePlugin;
1201 #endif
1202         ASSERT([package isKindOfClass:[WebPluginPackage class]]);
1203         return ObjectContentOtherPlugin;
1204     }
1205
1206     if ([WebFrameView _viewClassForMIMEType:type])
1207         return ObjectContentFrame;
1208     
1209     return ObjectContentNone;
1210
1211     END_BLOCK_OBJC_EXCEPTIONS;
1212
1213     return ObjectContentNone;
1214 }
1215
1216 static NSMutableArray* kit(const Vector<String>& vector)
1217 {
1218     unsigned len = vector.size();
1219     NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
1220     for (unsigned x = 0; x < len; x++)
1221         [array addObject:vector[x]];
1222     return array;
1223 }
1224
1225 static String parameterValue(const Vector<String>& paramNames, const Vector<String>& paramValues, const String& name)
1226 {
1227     size_t size = paramNames.size();
1228     ASSERT(size == paramValues.size());
1229     for (size_t i = 0; i < size; ++i) {
1230         if (equalIgnoringCase(paramNames[i], name))
1231             return paramValues[i];
1232     }
1233     return String();
1234 }
1235
1236 static NSView *pluginView(WebFrame *frame, WebPluginPackage *pluginPackage,
1237     NSArray *attributeNames, NSArray *attributeValues, NSURL *baseURL,
1238     DOMElement *element, BOOL loadManually)
1239 {
1240     WebHTMLView *docView = (WebHTMLView *)[[frame frameView] documentView];
1241     ASSERT([docView isKindOfClass:[WebHTMLView class]]);
1242         
1243     WebPluginController *pluginController = [docView _pluginController];
1244     
1245     // Store attributes in a dictionary so they can be passed to WebPlugins.
1246     NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:attributeValues forKeys:attributeNames];
1247     
1248     [pluginPackage load];
1249     Class viewFactory = [pluginPackage viewFactory];
1250     
1251     NSView *view = nil;
1252     NSDictionary *arguments = nil;
1253     
1254     if ([viewFactory respondsToSelector:@selector(plugInViewWithArguments:)]) {
1255         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1256             baseURL, WebPlugInBaseURLKey,
1257             attributes, WebPlugInAttributesKey,
1258             pluginController, WebPlugInContainerKey,
1259             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1260             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1261             element, WebPlugInContainingElementKey,
1262             nil];
1263         LOG(Plugins, "arguments:\n%@", arguments);
1264     } else if ([viewFactory respondsToSelector:@selector(pluginViewWithArguments:)]) {
1265         arguments = [NSDictionary dictionaryWithObjectsAndKeys:
1266             baseURL, WebPluginBaseURLKey,
1267             attributes, WebPluginAttributesKey,
1268             pluginController, WebPluginContainerKey,
1269             element, WebPlugInContainingElementKey,
1270             nil];
1271         LOG(Plugins, "arguments:\n%@", arguments);
1272     }
1273
1274     view = [WebPluginController plugInViewWithArguments:arguments fromPluginPackage:pluginPackage];
1275     [attributes release];
1276     return view;
1277 }
1278
1279 Widget* WebFrameLoaderClient::createPlugin(const IntSize& size, Element* element, const KURL& url,
1280     const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually)
1281 {
1282     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1283
1284     ASSERT(paramNames.size() == paramValues.size());
1285
1286     int errorCode = 0;
1287
1288     WebView *webView = getWebView(m_webFrame.get());
1289     SEL selector = @selector(webView:plugInViewWithArguments:);
1290     NSURL *URL = url;
1291
1292     if ([[webView UIDelegate] respondsToSelector:selector]) {
1293         NSMutableDictionary *attributes = [[NSMutableDictionary alloc] initWithObjects:kit(paramNames) forKeys:kit(paramValues)];
1294         NSDictionary *arguments = [[NSDictionary alloc] initWithObjectsAndKeys:
1295             attributes, WebPlugInAttributesKey,
1296             [NSNumber numberWithInt:loadManually ? WebPlugInModeFull : WebPlugInModeEmbed], WebPlugInModeKey,
1297             [NSNumber numberWithBool:!loadManually], WebPlugInShouldLoadMainResourceKey,
1298             kit(element), WebPlugInContainingElementKey,
1299             URL, WebPlugInBaseURLKey, // URL might be nil, so add it last
1300             nil];
1301
1302         NSView *view = CallUIDelegate(webView, selector, arguments);
1303
1304         [attributes release];
1305         [arguments release];
1306
1307         if (view)
1308             return new Widget(view);
1309     }
1310
1311     NSString *MIMEType;
1312     WebBasePluginPackage *pluginPackage;
1313     if (mimeType.isEmpty()) {
1314         MIMEType = nil;
1315         pluginPackage = nil;
1316     } else {
1317         MIMEType = mimeType;
1318         pluginPackage = [webView _pluginForMIMEType:mimeType];
1319     }
1320     
1321     NSString *extension = [[URL path] pathExtension];
1322     if (!pluginPackage && [extension length] != 0) {
1323         pluginPackage = [webView _pluginForExtension:extension];
1324         if (pluginPackage) {
1325             NSString *newMIMEType = [pluginPackage MIMETypeForExtension:extension];
1326             if ([newMIMEType length] != 0)
1327                 MIMEType = newMIMEType;
1328         }
1329     }
1330
1331     NSView *view = nil;
1332
1333     Document* document = core(m_webFrame.get())->document();
1334     NSURL *baseURL = document->baseURL();
1335     if (pluginPackage) {
1336         if ([pluginPackage isKindOfClass:[WebPluginPackage class]])
1337             view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, kit(paramNames), kit(paramValues), baseURL, kit(element), loadManually);
1338             
1339 #if ENABLE(NETSCAPE_PLUGIN_API)
1340         else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1341             WebNetscapePluginEmbeddedView *embeddedView = [[[WebNetscapePluginEmbeddedView alloc]
1342                 initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1343                 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1344                 URL:URL
1345                 baseURL:baseURL
1346                 MIMEType:MIMEType
1347                 attributeKeys:kit(paramNames)
1348                 attributeValues:kit(paramValues)
1349                 loadManually:loadManually
1350                 DOMElement:kit(element)] autorelease];
1351             view = embeddedView;
1352         } 
1353 #endif
1354     } else
1355         errorCode = WebKitErrorCannotFindPlugIn;
1356
1357     if (!errorCode && !view)
1358         errorCode = WebKitErrorCannotLoadPlugIn;
1359
1360     if (errorCode) {
1361         NSError *error = [[NSError alloc] _initWithPluginErrorCode:errorCode
1362             contentURL:URL
1363             pluginPageURL:document->completeURL(parseURL(parameterValue(paramNames, paramValues, "pluginspage")))
1364             pluginName:[pluginPackage name]
1365             MIMEType:MIMEType];
1366         WebNullPluginView *nullView = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1367             error:error DOMElement:kit(element)] autorelease];
1368         view = nullView;
1369         [error release];
1370     }
1371     
1372     ASSERT(view);
1373     return new Widget(view);
1374
1375     END_BLOCK_OBJC_EXCEPTIONS;
1376
1377     return 0;
1378 }
1379
1380 void WebFrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
1381 {
1382     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1383
1384     WebHTMLRepresentation *representation = (WebHTMLRepresentation *)[[m_webFrame.get() _dataSource] representation];
1385
1386     NSView *pluginView = pluginWidget->getView();
1387
1388 #if ENABLE(NETSCAPE_PLUGIN_API)
1389     if ([pluginView isKindOfClass:[WebNetscapePluginEmbeddedView class]])
1390         [representation _redirectDataToManualLoader:(WebNetscapePluginEmbeddedView *)pluginView forPluginView:pluginView];
1391     else {
1392 #else
1393     {
1394 #endif
1395         WebHTMLView *documentView = (WebHTMLView *)[[m_webFrame.get() frameView] documentView];
1396         ASSERT([documentView isKindOfClass:[WebHTMLView class]]);
1397         [representation _redirectDataToManualLoader:[documentView _pluginController] forPluginView:pluginView];
1398     }
1399
1400     END_BLOCK_OBJC_EXCEPTIONS;
1401 }
1402
1403 Widget* WebFrameLoaderClient::createJavaAppletWidget(const IntSize& size, Element* element, const KURL& baseURL, 
1404     const Vector<String>& paramNames, const Vector<String>& paramValues)
1405 {
1406     BEGIN_BLOCK_OBJC_EXCEPTIONS;
1407
1408     NSView *view = nil;
1409
1410     NSString *MIMEType = @"application/x-java-applet";
1411     
1412     WebView *webView = getWebView(m_webFrame.get());
1413
1414     WebBasePluginPackage *pluginPackage = [webView _pluginForMIMEType:MIMEType];
1415
1416     if (pluginPackage) {
1417         if ([pluginPackage isKindOfClass:[WebPluginPackage class]]) {
1418             // For some reason, the Java plug-in requires that we pass the dimension of the plug-in as attributes.
1419             NSMutableArray *names = kit(paramNames);
1420             NSMutableArray *values = kit(paramValues);
1421             if (parameterValue(paramNames, paramValues, "width").isNull()) {
1422                 [names addObject:@"width"];
1423                 [values addObject:[NSString stringWithFormat:@"%d", size.width()]];
1424             }
1425             if (parameterValue(paramNames, paramValues, "height").isNull()) {
1426                 [names addObject:@"height"];
1427                 [values addObject:[NSString stringWithFormat:@"%d", size.width()]];
1428             }
1429             view = pluginView(m_webFrame.get(), (WebPluginPackage *)pluginPackage, names, values, baseURL, kit(element), NO);
1430         } 
1431 #if ENABLE(NETSCAPE_PLUGIN_API)
1432         else if ([pluginPackage isKindOfClass:[WebNetscapePluginPackage class]]) {
1433             view = [[[WebNetscapePluginEmbeddedView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1434                 pluginPackage:(WebNetscapePluginPackage *)pluginPackage
1435                 URL:nil
1436                 baseURL:baseURL
1437                 MIMEType:MIMEType
1438                 attributeKeys:kit(paramNames)
1439                 attributeValues:kit(paramValues)
1440                 loadManually:NO
1441                 DOMElement:kit(element)] autorelease];
1442         } else {
1443             ASSERT_NOT_REACHED();
1444         }
1445 #endif
1446     }
1447
1448     if (!view) {
1449         NSError *error = [[NSError alloc] _initWithPluginErrorCode:WebKitErrorJavaUnavailable
1450             contentURL:nil
1451             pluginPageURL:nil
1452             pluginName:[pluginPackage name]
1453             MIMEType:MIMEType];
1454         view = [[[WebNullPluginView alloc] initWithFrame:NSMakeRect(0, 0, size.width(), size.height())
1455             error:error DOMElement:kit(element)] autorelease];
1456         [error release];
1457     }
1458
1459     ASSERT(view);
1460     return new Widget(view);
1461
1462     END_BLOCK_OBJC_EXCEPTIONS;
1463     
1464     return new Widget;
1465 }
1466
1467 String WebFrameLoaderClient::overrideMediaType() const
1468 {
1469     NSString* overrideType = [getWebView(m_webFrame.get()) mediaStyle];
1470     if (overrideType)
1471         return overrideType;
1472     return String();
1473 }
1474
1475 void WebFrameLoaderClient::windowObjectCleared()
1476 {
1477     Frame *frame = core(m_webFrame.get());
1478     WebView *webView = getWebView(m_webFrame.get());
1479     WebFrameLoadDelegateImplementationCache* implementations = WebViewGetFrameLoadDelegateImplementations(webView);
1480     if (implementations->didClearWindowObjectForFrameFunc) {
1481         CallFrameLoadDelegate(implementations->didClearWindowObjectForFrameFunc, webView, @selector(webView:didClearWindowObject:forFrame:),
1482             frame->windowScriptObject(), m_webFrame.get());
1483     } else if (implementations->windowScriptObjectAvailableFunc) {
1484         CallFrameLoadDelegate(implementations->windowScriptObjectAvailableFunc, webView, @selector(webView:windowScriptObjectAvailable:),
1485             frame->windowScriptObject());
1486     }
1487
1488     if ([webView scriptDebugDelegate] || [WebScriptDebugServer listenerCount]) {
1489         [m_webFrame.get() _detachScriptDebugger];
1490         [m_webFrame.get() _attachScriptDebugger];
1491     }
1492 }
1493
1494 void WebFrameLoaderClient::registerForIconNotification(bool listen)
1495 {
1496     [[m_webFrame.get() webView] _registerForIconNotification:listen];
1497 }
1498
1499 void WebFrameLoaderClient::didPerformFirstNavigation() const
1500 {
1501     WebPreferences *preferences = [[m_webFrame.get() webView] preferences];
1502     if ([preferences automaticallyDetectsCacheModel] && [preferences cacheModel] < WebCacheModelDocumentBrowser)
1503         [preferences setCacheModel:WebCacheModelDocumentBrowser];
1504 }
1505
1506 jobject WebFrameLoaderClient::javaApplet(NSView* view)
1507 {
1508     if ([view respondsToSelector:@selector(webPlugInGetApplet)])
1509         return [view webPlugInGetApplet];
1510
1511     // Compatibility with older versions of Java.
1512     // FIXME: Do we still need this?
1513     if ([view respondsToSelector:@selector(pollForAppletInWindow:)])
1514         return [view pollForAppletInWindow:[[m_webFrame.get() frameView] window]];
1515
1516     return 0;
1517 }
1518
1519 @implementation WebFramePolicyListener
1520
1521 #ifndef BUILDING_ON_TIGER
1522 + (void)initialize
1523 {
1524     WebCoreObjCFinalizeOnMainThread(self);
1525 }
1526 #endif
1527
1528 - (id)initWithWebCoreFrame:(Frame*)frame
1529 {
1530     self = [self init];
1531     if (!self)
1532         return nil;
1533     frame->ref();
1534     m_frame = frame;
1535     return self;
1536 }
1537
1538 - (void)invalidate
1539 {
1540     if (m_frame) {
1541         m_frame->deref();
1542         m_frame = 0;
1543     }
1544 }
1545
1546 - (void)dealloc
1547 {
1548     if (m_frame)
1549         m_frame->deref();
1550     [super dealloc];
1551 }
1552
1553 - (void)finalize
1554 {
1555     ASSERT_MAIN_THREAD();
1556     if (m_frame)
1557         m_frame->deref();
1558     [super finalize];
1559 }
1560
1561 - (void)receivedPolicyDecision:(PolicyAction)action
1562 {
1563     RefPtr<Frame> frame = adoptRef(m_frame);
1564     m_frame = 0;
1565     if (frame)
1566         static_cast<WebFrameLoaderClient*>(frame->loader()->client())->receivedPolicyDecison(action);
1567 }
1568
1569 - (void)ignore
1570 {
1571     [self receivedPolicyDecision:PolicyIgnore];
1572 }
1573
1574 - (void)download
1575 {
1576     [self receivedPolicyDecision:PolicyDownload];
1577 }
1578
1579 - (void)use
1580 {
1581     [self receivedPolicyDecision:PolicyUse];
1582 }
1583
1584 - (void)continue
1585 {
1586     [self receivedPolicyDecision:PolicyUse];
1587 }
1588
1589 @end