1/*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#import "WebDelegateImplementationCaching.h"
31
32#import "WebKitLogging.h"
33#import "WebView.h"
34#import "WebViewData.h"
35#import <objc/objc-runtime.h>
36
37@implementation WebView (WebDelegateImplementationCaching)
38
39WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
40{
41    static WebResourceDelegateImplementationCache empty;
42    if (!webView)
43        return &empty;
44    return &webView->_private->resourceLoadDelegateImplementations;
45}
46
47WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
48{
49    static WebFrameLoadDelegateImplementationCache empty;
50    if (!webView)
51        return &empty;
52    return &webView->_private->frameLoadDelegateImplementations;
53}
54
55WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView)
56{
57    static WebScriptDebugDelegateImplementationCache empty;
58    if (!webView)
59        return &empty;
60    return &webView->_private->scriptDebugDelegateImplementations;
61}
62
63WebHistoryDelegateImplementationCache* WebViewGetHistoryDelegateImplementations(WebView *webView)
64{
65    static WebHistoryDelegateImplementationCache empty;
66    if (!webView)
67        return &empty;
68    return &webView->_private->historyDelegateImplementations;
69}
70
71// We use these functions to call the delegates and block exceptions. These functions are
72// declared inside a WebView category to get direct access to the delegate data memebers,
73// preventing more ObjC message dispatch and compensating for the expense of the @try/@catch.
74
75typedef float (*ObjCMsgSendFPRet)(id, SEL, ...);
76#if defined(__i386__)
77static const ObjCMsgSendFPRet objc_msgSend_float_return = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend_fpret);
78#else
79static const ObjCMsgSendFPRet objc_msgSend_float_return = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend);
80#endif
81
82static inline id CallDelegate(WebView *self, id delegate, SEL selector)
83{
84    if (!delegate || ![delegate respondsToSelector:selector])
85        return nil;
86    if (!self->_private->catchesDelegateExceptions)
87        return objc_msgSend(delegate, selector, self);
88    @try {
89        return objc_msgSend(delegate, selector, self);
90    } @catch(id exception) {
91        ReportDiscardedDelegateException(selector, exception);
92    }
93    return nil;
94}
95
96static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object)
97{
98    if (!delegate || ![delegate respondsToSelector:selector])
99        return nil;
100    if (!self->_private->catchesDelegateExceptions)
101        return objc_msgSend(delegate, selector, self, object);
102    @try {
103        return objc_msgSend(delegate, selector, self, object);
104    } @catch(id exception) {
105        ReportDiscardedDelegateException(selector, exception);
106    }
107    return nil;
108}
109
110static inline id CallDelegate(WebView *self, id delegate, SEL selector, NSRect rect)
111{
112    if (!delegate || ![delegate respondsToSelector:selector])
113        return nil;
114    if (!self->_private->catchesDelegateExceptions)
115        return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
116    @try {
117        return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
118    } @catch(id exception) {
119        ReportDiscardedDelegateException(selector, exception);
120    }
121    return nil;
122}
123
124static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2)
125{
126    if (!delegate || ![delegate respondsToSelector:selector])
127        return nil;
128    if (!self->_private->catchesDelegateExceptions)
129        return objc_msgSend(delegate, selector, self, object1, object2);
130    @try {
131        return objc_msgSend(delegate, selector, self, object1, object2);
132    } @catch(id exception) {
133        ReportDiscardedDelegateException(selector, exception);
134    }
135    return nil;
136}
137
138static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, BOOL boolean)
139{
140    if (!delegate || ![delegate respondsToSelector:selector])
141        return nil;
142    if (!self->_private->catchesDelegateExceptions)
143        return objc_msgSend(delegate, selector, self, object, boolean);
144    @try {
145        return objc_msgSend(delegate, selector, self, object, boolean);
146    } @catch(id exception) {
147        ReportDiscardedDelegateException(selector, exception);
148    }
149    return nil;
150}
151
152static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
153{
154    if (!delegate || ![delegate respondsToSelector:selector])
155        return nil;
156    if (!self->_private->catchesDelegateExceptions)
157        return objc_msgSend(delegate, selector, self, object1, object2, object3);
158    @try {
159        return objc_msgSend(delegate, selector, self, object1, object2, object3);
160    } @catch(id exception) {
161        ReportDiscardedDelegateException(selector, exception);
162    }
163    return nil;
164}
165
166static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, NSUInteger integer)
167{
168    if (!delegate || ![delegate respondsToSelector:selector])
169        return nil;
170    if (!self->_private->catchesDelegateExceptions)
171        return objc_msgSend(delegate, selector, self, object, integer);
172    @try {
173        return objc_msgSend(delegate, selector, self, object, integer);
174    } @catch(id exception) {
175        ReportDiscardedDelegateException(selector, exception);
176    }
177    return nil;
178}
179
180static inline float CallDelegateReturningFloat(WebView *self, id delegate, SEL selector)
181{
182    if (!delegate || ![delegate respondsToSelector:selector])
183        return 0.0f;
184    if (!self->_private->catchesDelegateExceptions)
185        return objc_msgSend_float_return(delegate, selector, self);
186    @try {
187        return objc_msgSend_float_return(delegate, selector, self);
188    } @catch(id exception) {
189        ReportDiscardedDelegateException(selector, exception);
190    }
191    return 0.0f;
192}
193
194static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector)
195{
196    if (!delegate || ![delegate respondsToSelector:selector])
197        return result;
198    if (!self->_private->catchesDelegateExceptions)
199        return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
200    @try {
201        return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
202    } @catch(id exception) {
203        ReportDiscardedDelegateException(selector, exception);
204    }
205    return result;
206}
207
208static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object)
209{
210    if (!delegate || ![delegate respondsToSelector:selector])
211        return result;
212    if (!self->_private->catchesDelegateExceptions)
213        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
214    @try {
215        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
216    } @catch(id exception) {
217        ReportDiscardedDelegateException(selector, exception);
218    }
219    return result;
220}
221
222static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object, BOOL boolean)
223{
224    if (!delegate || ![delegate respondsToSelector:selector])
225        return result;
226    if (!self->_private->catchesDelegateExceptions)
227        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
228    @try {
229        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
230    } @catch(id exception) {
231        ReportDiscardedDelegateException(selector, exception);
232    }
233    return result;
234}
235
236static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object, BOOL boolean, id object2)
237{
238    if (!delegate || ![delegate respondsToSelector:selector])
239        return result;
240    if (!self->_private->catchesDelegateExceptions)
241        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL, id)>(objc_msgSend)(delegate, selector, self, object, boolean, object2);
242    @try {
243        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL, id)>(objc_msgSend)(delegate, selector, self, object, boolean, object2);
244    } @catch(id exception) {
245        ReportDiscardedDelegateException(selector, exception);
246    }
247    return result;
248}
249
250static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object1, id object2)
251{
252    if (!delegate || ![delegate respondsToSelector:selector])
253        return result;
254    if (!self->_private->catchesDelegateExceptions)
255        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
256    @try {
257        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
258    } @catch(id exception) {
259        ReportDiscardedDelegateException(selector, exception);
260    }
261    return result;
262}
263
264static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector)
265{
266    if (!delegate)
267        return nil;
268    if (!self->_private->catchesDelegateExceptions)
269        return implementation(delegate, selector, self);
270    @try {
271        return implementation(delegate, selector, self);
272    } @catch(id exception) {
273        ReportDiscardedDelegateException(selector, exception);
274    }
275    return nil;
276}
277
278static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object)
279{
280    if (!delegate)
281        return nil;
282    if (!self->_private->catchesDelegateExceptions)
283        return implementation(delegate, selector, self, object);
284    @try {
285        return implementation(delegate, selector, self, object);
286    } @catch(id exception) {
287        ReportDiscardedDelegateException(selector, exception);
288    }
289    return nil;
290}
291
292static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2)
293{
294    if (!delegate)
295        return nil;
296    if (!self->_private->catchesDelegateExceptions)
297        return implementation(delegate, selector, self, object1, object2);
298    @try {
299        return implementation(delegate, selector, self, object1, object2);
300    } @catch(id exception) {
301        ReportDiscardedDelegateException(selector, exception);
302    }
303    return nil;
304}
305
306static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
307{
308    if (!delegate)
309        return nil;
310    if (!self->_private->catchesDelegateExceptions)
311        return implementation(delegate, selector, self, object1, object2, object3);
312    @try {
313        return implementation(delegate, selector, self, object1, object2, object3);
314    } @catch(id exception) {
315        ReportDiscardedDelegateException(selector, exception);
316    }
317    return nil;
318}
319
320static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3, id object4)
321{
322    if (!delegate)
323        return nil;
324    if (!self->_private->catchesDelegateExceptions)
325        return implementation(delegate, selector, self, object1, object2, object3, object4);
326    @try {
327        return implementation(delegate, selector, self, object1, object2, object3, object4);
328    } @catch(id exception) {
329        ReportDiscardedDelegateException(selector, exception);
330    }
331    return nil;
332}
333
334static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2)
335{
336    if (!delegate)
337        return nil;
338    if (!self->_private->catchesDelegateExceptions)
339        return implementation(delegate, selector, self, object1, integer, object2);
340    @try {
341        return implementation(delegate, selector, self, object1, integer, object2);
342    } @catch(id exception) {
343        ReportDiscardedDelegateException(selector, exception);
344    }
345    return nil;
346}
347
348static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, int integer2, id object2)
349{
350    if (!delegate)
351        return nil;
352    if (!self->_private->catchesDelegateExceptions)
353        return implementation(delegate, selector, self, object1, integer1, integer2, object2);
354    @try {
355        return implementation(delegate, selector, self, object1, integer1, integer2, object2);
356    } @catch(id exception) {
357        ReportDiscardedDelegateException(selector, exception);
358    }
359    return nil;
360}
361
362static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, BOOL boolean, NSInteger integer1, int integer2, id object2)
363{
364    if (!delegate)
365        return nil;
366    if (!self->_private->catchesDelegateExceptions)
367        return implementation(delegate, selector, self, object1, boolean, integer1, integer2, object2);
368    @try {
369        return implementation(delegate, selector, self, object1, boolean, integer1, integer2, object2);
370    } @catch(id exception) {
371        ReportDiscardedDelegateException(selector, exception);
372    }
373    return nil;
374}
375
376static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3)
377{
378    if (!delegate)
379        return nil;
380    if (!self->_private->catchesDelegateExceptions)
381        return implementation(delegate, selector, self, object1, object2, integer, object3);
382    @try {
383        return implementation(delegate, selector, self, object1, object2, integer, object3);
384    } @catch(id exception) {
385        ReportDiscardedDelegateException(selector, exception);
386    }
387    return nil;
388}
389
390static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
391{
392    if (!delegate)
393        return nil;
394    if (!self->_private->catchesDelegateExceptions)
395        return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3);
396    @try {
397        return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3);
398    } @catch(id exception) {
399        ReportDiscardedDelegateException(selector, exception);
400    }
401    return nil;
402}
403
404static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
405{
406    if (!delegate)
407        return nil;
408    if (!self->_private->catchesDelegateExceptions)
409        return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
410    @try {
411        return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
412    } @catch(id exception) {
413        ReportDiscardedDelegateException(selector, exception);
414    }
415    return nil;
416}
417
418static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
419{
420    if (!delegate)
421        return nil;
422    if (!self->_private->catchesDelegateExceptions)
423        return implementation(delegate, selector, self, object1, interval, object2, object3);
424    @try {
425        return implementation(delegate, selector, self, object1, interval, object2, object3);
426    } @catch(id exception) {
427        ReportDiscardedDelegateException(selector, exception);
428    }
429    return nil;
430}
431
432id CallUIDelegate(WebView *self, SEL selector)
433{
434    return CallDelegate(self, self->_private->UIDelegate, selector);
435}
436
437id CallUIDelegate(WebView *self, SEL selector, id object)
438{
439    return CallDelegate(self, self->_private->UIDelegate, selector, object);
440}
441
442id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean)
443{
444    return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean);
445}
446
447id CallUIDelegate(WebView *self, SEL selector, NSRect rect)
448{
449    return CallDelegate(self, self->_private->UIDelegate, selector, rect);
450}
451
452id CallUIDelegate(WebView *self, SEL selector, id object1, id object2)
453{
454    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2);
455}
456
457id CallUIDelegate(WebView *self, SEL selector, id object1, id object2, id object3)
458{
459    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2, object3);
460}
461
462id CallUIDelegate(WebView *self, SEL selector, id object, NSUInteger integer)
463{
464    return CallDelegate(self, self->_private->UIDelegate, selector, object, integer);
465}
466
467float CallUIDelegateReturningFloat(WebView *self, SEL selector)
468{
469    return CallDelegateReturningFloat(self, self->_private->UIDelegate, selector);
470}
471
472BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector)
473{
474    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector);
475}
476
477BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object)
478{
479    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object);
480}
481
482BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean)
483{
484    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean);
485}
486
487BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean, id object2)
488{
489    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean, object2);
490}
491
492BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, id object2)
493{
494    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object1, object2);
495}
496
497id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector)
498{
499    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector);
500}
501
502id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object)
503{
504    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object);
505}
506
507id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
508{
509    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2);
510}
511
512id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
513{
514    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3);
515}
516
517id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
518{
519    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3, object4);
520}
521
522id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
523{
524    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, interval, object2, object3);
525}
526
527id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
528{
529    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2);
530}
531
532id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
533{
534    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3);
535}
536
537id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
538{
539    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4);
540}
541
542id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2)
543{
544    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2);
545}
546
547id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
548{
549    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3);
550}
551
552BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, WebView *self, SEL selector, id object1)
553{
554    if (!self->_private->catchesDelegateExceptions)
555        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1);
556    @try {
557        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1);
558    } @catch(id exception) {
559        ReportDiscardedDelegateException(selector, exception);
560    }
561    return result;
562}
563
564BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, WebView *self, SEL selector, id object1, id object2)
565{
566    if (!self->_private->catchesDelegateExceptions)
567        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
568    @try {
569        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
570    } @catch(id exception) {
571        ReportDiscardedDelegateException(selector, exception);
572    }
573    return result;
574}
575
576BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
577{
578    if (!self->_private->catchesDelegateExceptions)
579        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2, object3);
580    @try {
581        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2, object3);
582    } @catch(id exception) {
583        ReportDiscardedDelegateException(selector, exception);
584    }
585    return result;
586}
587
588id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
589{
590    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, object2, integer, object3);
591}
592
593id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
594{
595    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, object2, integer2, object3);
596}
597
598id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
599{
600    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer, object2, object3, object4);
601}
602
603id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, int integer2, id object2)
604{
605    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, integer2, object2);
606}
607
608id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, BOOL boolean, NSInteger integer1, int integer2, id object2)
609{
610    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, boolean, integer1, integer2, object2);
611}
612
613id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector)
614{
615    return CallDelegate(implementation, self, self->_private->historyDelegate, selector);
616}
617
618id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
619{
620    return CallDelegate(implementation, self, self->_private->historyDelegate, selector, object1, object2);
621}
622
623id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
624{
625    return CallDelegate(implementation, self, self->_private->historyDelegate, selector, object1, object2, object3);
626}
627
628// The form delegate needs to have it's own implementation, because the first argument is never the WebView
629
630id CallFormDelegate(WebView *self, SEL selector, id object1, id object2)
631{
632    id delegate = self->_private->formDelegate;
633    if (!delegate || ![delegate respondsToSelector:selector])
634        return nil;
635    if (!self->_private->catchesDelegateExceptions)
636        return objc_msgSend(delegate, selector, object1, object2);
637    @try {
638        return objc_msgSend(delegate, selector, object1, object2);
639    } @catch(id exception) {
640        ReportDiscardedDelegateException(selector, exception);
641    }
642    return nil;
643}
644
645id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5)
646{
647    id delegate = self->_private->formDelegate;
648    if (!delegate || ![delegate respondsToSelector:selector])
649        return nil;
650    if (!self->_private->catchesDelegateExceptions)
651        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
652    @try {
653        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
654    } @catch(id exception) {
655        ReportDiscardedDelegateException(selector, exception);
656    }
657    return nil;
658}
659
660BOOL CallFormDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, SEL selectorArg, id object2)
661{
662    id delegate = self->_private->formDelegate;
663    if (!delegate || ![delegate respondsToSelector:selector])
664        return result;
665    if (!self->_private->catchesDelegateExceptions)
666        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
667    @try {
668        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
669    } @catch(id exception) {
670        ReportDiscardedDelegateException(selector, exception);
671    }
672    return result;
673}
674
675@end
676