• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, NSInteger 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, id object2, NSInteger integer, id object3)
363{
364    if (!delegate)
365        return nil;
366    if (!self->_private->catchesDelegateExceptions)
367        return implementation(delegate, selector, self, object1, object2, integer, object3);
368    @try {
369        return implementation(delegate, selector, self, object1, object2, integer, object3);
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, NSInteger integer1, id object2, NSInteger integer2, id object3)
377{
378    if (!delegate)
379        return nil;
380    if (!self->_private->catchesDelegateExceptions)
381        return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3);
382    @try {
383        return implementation(delegate, selector, self, object1, integer1, object2, integer2, 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 integer, id object2, id object3, id object4)
391{
392    if (!delegate)
393        return nil;
394    if (!self->_private->catchesDelegateExceptions)
395        return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
396    @try {
397        return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
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, NSTimeInterval interval, id object2, id object3)
405{
406    if (!delegate)
407        return nil;
408    if (!self->_private->catchesDelegateExceptions)
409        return implementation(delegate, selector, self, object1, interval, object2, object3);
410    @try {
411        return implementation(delegate, selector, self, object1, interval, object2, object3);
412    } @catch(id exception) {
413        ReportDiscardedDelegateException(selector, exception);
414    }
415    return nil;
416}
417
418id CallUIDelegate(WebView *self, SEL selector)
419{
420    return CallDelegate(self, self->_private->UIDelegate, selector);
421}
422
423id CallUIDelegate(WebView *self, SEL selector, id object)
424{
425    return CallDelegate(self, self->_private->UIDelegate, selector, object);
426}
427
428id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean)
429{
430    return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean);
431}
432
433id CallUIDelegate(WebView *self, SEL selector, NSRect rect)
434{
435    return CallDelegate(self, self->_private->UIDelegate, selector, rect);
436}
437
438id CallUIDelegate(WebView *self, SEL selector, id object1, id object2)
439{
440    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2);
441}
442
443id CallUIDelegate(WebView *self, SEL selector, id object1, id object2, id object3)
444{
445    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2, object3);
446}
447
448id CallUIDelegate(WebView *self, SEL selector, id object, NSUInteger integer)
449{
450    return CallDelegate(self, self->_private->UIDelegate, selector, object, integer);
451}
452
453float CallUIDelegateReturningFloat(WebView *self, SEL selector)
454{
455    return CallDelegateReturningFloat(self, self->_private->UIDelegate, selector);
456}
457
458BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector)
459{
460    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector);
461}
462
463BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object)
464{
465    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object);
466}
467
468BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean)
469{
470    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean);
471}
472
473BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean, id object2)
474{
475    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean, object2);
476}
477
478BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, id object2)
479{
480    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object1, object2);
481}
482
483id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector)
484{
485    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector);
486}
487
488id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object)
489{
490    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object);
491}
492
493id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
494{
495    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2);
496}
497
498id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
499{
500    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3);
501}
502
503id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
504{
505    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3, object4);
506}
507
508id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
509{
510    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, interval, object2, object3);
511}
512
513id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
514{
515    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2);
516}
517
518id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
519{
520    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3);
521}
522
523id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
524{
525    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4);
526}
527
528id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2)
529{
530    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2);
531}
532
533id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
534{
535    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3);
536}
537
538BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, WebView *self, SEL selector, id object1, id object2)
539{
540    if (!self->_private->catchesDelegateExceptions)
541        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
542    @try {
543        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
544    } @catch(id exception) {
545        ReportDiscardedDelegateException(selector, exception);
546    }
547    return result;
548}
549
550id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
551{
552    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, object2, integer, object3);
553}
554
555id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
556{
557    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, object2, integer2, object3);
558}
559
560id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
561{
562    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer, object2, object3, object4);
563}
564
565id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, NSInteger integer2, id object2)
566{
567    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, integer2, object2);
568}
569
570id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector)
571{
572    return CallDelegate(implementation, self, self->_private->historyDelegate, selector);
573}
574
575id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
576{
577    return CallDelegate(implementation, self, self->_private->historyDelegate, selector, object1, object2);
578}
579
580id CallHistoryDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
581{
582    return CallDelegate(implementation, self, self->_private->historyDelegate, selector, object1, object2, object3);
583}
584
585// The form delegate needs to have it's own implementation, because the first argument is never the WebView
586
587id CallFormDelegate(WebView *self, SEL selector, id object1, id object2)
588{
589    id delegate = self->_private->formDelegate;
590    if (!delegate || ![delegate respondsToSelector:selector])
591        return nil;
592    if (!self->_private->catchesDelegateExceptions)
593        return objc_msgSend(delegate, selector, object1, object2);
594    @try {
595        return objc_msgSend(delegate, selector, object1, object2);
596    } @catch(id exception) {
597        ReportDiscardedDelegateException(selector, exception);
598    }
599    return nil;
600}
601
602id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5)
603{
604    id delegate = self->_private->formDelegate;
605    if (!delegate || ![delegate respondsToSelector:selector])
606        return nil;
607    if (!self->_private->catchesDelegateExceptions)
608        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
609    @try {
610        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
611    } @catch(id exception) {
612        ReportDiscardedDelegateException(selector, exception);
613    }
614    return nil;
615}
616
617BOOL CallFormDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, SEL selectorArg, id object2)
618{
619    id delegate = self->_private->formDelegate;
620    if (!delegate || ![delegate respondsToSelector:selector])
621        return result;
622    if (!self->_private->catchesDelegateExceptions)
623        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
624    @try {
625        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
626    } @catch(id exception) {
627        ReportDiscardedDelegateException(selector, exception);
628    }
629    return result;
630}
631
632@end
633