]>
Commit | Line | Data |
---|---|---|
1e4922b8 JF |
1 | #include <UIKit/UIKit.h> |
2 | #include "iPhonePrivate.h" | |
3 | ||
4 | #include "UCPlatform.h" | |
5 | ||
3cb572d2 JF |
6 | #include <UICaboodle/BrowserView.h> |
7 | #include <UICaboodle/UCLocalize.h> | |
61b13cae | 8 | |
1e4922b8 | 9 | //#include <QuartzCore/CALayer.h> |
61b13cae JF |
10 | // XXX: fix the minimum requirement |
11 | extern NSString * const kCAFilterNearest; | |
bde2d79b | 12 | |
9d7f5e2d | 13 | #include <WebCore/WebCoreThread.h> |
1e4922b8 JF |
14 | |
15 | #include <WebKit/WebPolicyDelegate.h> | |
16 | #include <WebKit/WebPreferences.h> | |
17 | ||
18 | #include <WebKit/DOMCSSPrimitiveValue.h> | |
19 | #include <WebKit/DOMCSSStyleDeclaration.h> | |
20 | #include <WebKit/DOMDocument.h> | |
21 | #include <WebKit/DOMHTMLBodyElement.h> | |
22 | #include <WebKit/DOMRGBColor.h> | |
23 | ||
24 | //#include <WebCore/Page.h> | |
25 | //#include <WebCore/Settings.h> | |
9d7f5e2d | 26 | |
61b13cae JF |
27 | #include "substrate.h" |
28 | ||
13bb1e92 | 29 | #define ForSaurik 0 |
017b2b71 | 30 | |
c2292b80 JF |
31 | template <typename Type_> |
32 | static inline void CYRelease(Type_ &value) { | |
33 | if (value != nil) { | |
34 | [value release]; | |
35 | value = nil; | |
36 | } | |
37 | } | |
d3bef7bc | 38 | |
c2292b80 JF |
39 | @interface WebView (Apple) |
40 | - (void) _setLayoutInterval:(float)interval; | |
41 | @end | |
42 | ||
43 | @interface WebPreferences (Apple) | |
44 | + (void) _setInitialDefaultTextEncodingToSystemEncoding; | |
45 | - (void) _setLayoutInterval:(NSInteger)interval; | |
46 | - (void) setOfflineWebApplicationCacheEnabled:(BOOL)enabled; | |
47 | @end | |
5d8f1006 | 48 | |
04700693 | 49 | /* Indirect Delegate {{{ */ |
1e4922b8 JF |
50 | @interface IndirectDelegate : NSObject < |
51 | HookProtocol | |
52 | > { | |
04700693 JF |
53 | _transient volatile id delegate_; |
54 | } | |
55 | ||
56 | - (void) setDelegate:(id)delegate; | |
57 | - (id) initWithDelegate:(id)delegate; | |
58 | @end | |
59 | ||
60 | @implementation IndirectDelegate | |
61 | ||
62 | - (void) setDelegate:(id)delegate { | |
63 | delegate_ = delegate; | |
64 | } | |
65 | ||
66 | - (id) initWithDelegate:(id)delegate { | |
67 | delegate_ = delegate; | |
68 | return self; | |
69 | } | |
70 | ||
1e4922b8 JF |
71 | - (void) didDismissModalViewController { |
72 | if (delegate_ != nil) | |
73 | return [delegate_ didDismissModalViewController]; | |
74 | } | |
75 | ||
9d7f5e2d JF |
76 | - (IMP) methodForSelector:(SEL)sel { |
77 | if (IMP method = [super methodForSelector:sel]) | |
78 | return method; | |
79 | fprintf(stderr, "methodForSelector:[%s] == NULL\n", sel_getName(sel)); | |
80 | return NULL; | |
81 | } | |
82 | ||
04700693 | 83 | - (BOOL) respondsToSelector:(SEL)sel { |
9d7f5e2d JF |
84 | if ([super respondsToSelector:sel]) |
85 | return YES; | |
86 | // XXX: WebThreadCreateNSInvocation returns nil | |
87 | //fprintf(stderr, "[%s]R?%s\n", class_getName(self->isa), sel_getName(sel)); | |
88 | return delegate_ == nil ? NO : [delegate_ respondsToSelector:sel]; | |
04700693 JF |
89 | } |
90 | ||
91 | - (NSMethodSignature *) methodSignatureForSelector:(SEL)sel { | |
9d7f5e2d JF |
92 | if (NSMethodSignature *method = [super methodSignatureForSelector:sel]) |
93 | return method; | |
94 | //fprintf(stderr, "[%s]S?%s\n", class_getName(self->isa), sel_getName(sel)); | |
04700693 JF |
95 | if (delegate_ != nil) |
96 | if (NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel]) | |
97 | return sig; | |
98 | // XXX: I fucking hate Apple so very very bad | |
99 | return [NSMethodSignature signatureWithObjCTypes:"v@:"]; | |
100 | } | |
101 | ||
102 | - (void) forwardInvocation:(NSInvocation *)inv { | |
103 | SEL sel = [inv selector]; | |
104 | if (delegate_ != nil && [delegate_ respondsToSelector:sel]) | |
105 | [inv invokeWithTarget:delegate_]; | |
106 | } | |
107 | ||
108 | @end | |
109 | /* }}} */ | |
110 | ||
61b13cae | 111 | @implementation WebScriptObject (UICaboodle) |
9d7f5e2d | 112 | |
485f16d6 | 113 | - (NSUInteger) count { |
9d7f5e2d JF |
114 | id length([self valueForKey:@"length"]); |
115 | if ([length respondsToSelector:@selector(intValue)]) | |
116 | return [length intValue]; | |
117 | else | |
118 | return 0; | |
119 | } | |
120 | ||
121 | - (id) objectAtIndex:(unsigned)index { | |
122 | return [self webScriptValueAtIndex:index]; | |
123 | } | |
124 | ||
125 | @end | |
126 | ||
c2292b80 JF |
127 | // CYWebPolicyDecision* {{{ |
128 | enum CYWebPolicyDecision { | |
129 | CYWebPolicyDecisionUnknown, | |
130 | CYWebPolicyDecisionDownload, | |
131 | CYWebPolicyDecisionIgnore, | |
132 | CYWebPolicyDecisionUse, | |
133 | }; | |
134 | ||
135 | @interface CYWebPolicyDecisionMediator : NSObject < | |
136 | WebPolicyDecisionListener | |
137 | > { | |
138 | id<WebPolicyDecisionListener> listener_; | |
139 | CYWebPolicyDecision decision_; | |
3c83edee | 140 | } |
c2292b80 JF |
141 | |
142 | - (id) initWithListener:(id<WebPolicyDecisionListener>)listener; | |
143 | ||
144 | - (CYWebPolicyDecision) decision; | |
145 | - (bool) decided; | |
146 | - (bool) decide; | |
147 | ||
3c83edee RP |
148 | @end |
149 | ||
c2292b80 | 150 | @implementation CYWebPolicyDecisionMediator |
3c83edee | 151 | |
c2292b80 JF |
152 | - (id) initWithListener:(id<WebPolicyDecisionListener>)listener { |
153 | if ((self = [super init]) != nil) { | |
154 | listener_ = listener; | |
155 | } return self; | |
156 | } | |
3c83edee | 157 | |
c2292b80 JF |
158 | - (CYWebPolicyDecision) decision { |
159 | return decision_; | |
160 | } | |
161 | ||
162 | - (bool) decided { | |
163 | return decision_ != CYWebPolicyDecisionUnknown; | |
164 | } | |
165 | ||
166 | - (bool) decide { | |
167 | switch (decision_) { | |
168 | case CYWebPolicyDecisionUnknown: | |
169 | default: | |
170 | return false; | |
171 | ||
172 | case CYWebPolicyDecisionDownload: [listener_ download]; break; | |
173 | case CYWebPolicyDecisionIgnore: [listener_ ignore]; break; | |
174 | case CYWebPolicyDecisionUse: [listener_ use]; break; | |
175 | } | |
176 | ||
177 | return true; | |
178 | } | |
179 | ||
180 | - (void) download { | |
181 | decision_ = CYWebPolicyDecisionDownload; | |
3c83edee RP |
182 | } |
183 | ||
c2292b80 JF |
184 | - (void) ignore { |
185 | decision_ = CYWebPolicyDecisionIgnore; | |
186 | } | |
187 | ||
188 | - (void) use { | |
189 | decision_ = CYWebPolicyDecisionUse; | |
3c83edee RP |
190 | } |
191 | ||
192 | @end | |
c2292b80 | 193 | // }}} |
3c83edee | 194 | |
c2292b80 | 195 | @implementation CYWebView : UIWebView |
4825688a | 196 | |
c2292b80 JF |
197 | - (id) initWithFrame:(CGRect)frame { |
198 | if ((self = [super initWithFrame:frame]) != nil) { | |
199 | } return self; | |
200 | } | |
4825688a | 201 | |
c2292b80 JF |
202 | - (void) dealloc { |
203 | [super dealloc]; | |
204 | } | |
bde2d79b | 205 | |
c2292b80 JF |
206 | - (id<CYWebViewDelegate>) delegate { |
207 | return (id<CYWebViewDelegate>) [super delegate]; | |
208 | } | |
bde2d79b | 209 | |
c2292b80 JF |
210 | /*- (WebView *) webView:(WebView *)view createWebViewWithRequest:(NSURLRequest *)request { |
211 | NSLog(@"createWebViewWithRequest:%@", request); | |
212 | WebView *created(nil); // XXX | |
213 | if (created == nil && [super respondsToSelector:@selector(webView:createWebViewWithRequest:)]) | |
214 | return [super webView:view createWebViewWithRequest:request]; | |
215 | else | |
216 | return created; | |
217 | }*/ | |
4825688a | 218 | |
c2292b80 JF |
219 | - (void) webView:(WebView *)view decidePolicyForNavigationAction:(NSDictionary *)action request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { |
220 | CYWebPolicyDecisionMediator *mediator([[[CYWebPolicyDecisionMediator alloc] initWithListener:listener] autorelease]); | |
221 | [[self delegate] webView:view decidePolicyForNavigationAction:action request:request frame:frame decisionListener:mediator]; | |
222 | if (![mediator decided] && [super respondsToSelector:@selector(webView:decidePolicyForNavigationAction:request:frame:decisionListener:)]) | |
223 | [super webView:view decidePolicyForNavigationAction:action request:request frame:frame decisionListener:mediator]; | |
224 | [mediator decide]; | |
225 | } | |
4825688a | 226 | |
c2292b80 JF |
227 | - (void) webView:(WebView *)view decidePolicyForNewWindowAction:(NSDictionary *)action request:(NSURLRequest *)request newFrameName:(NSString *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { |
228 | CYWebPolicyDecisionMediator *mediator([[[CYWebPolicyDecisionMediator alloc] initWithListener:listener] autorelease]); | |
229 | [[self delegate] webView:view decidePolicyForNewWindowAction:action request:request newFrameName:frame decisionListener:mediator]; | |
230 | if (![mediator decided] && [super respondsToSelector:@selector(webView:decidePolicyForNewWindowAction:request:newFrameName:decisionListener:)]) | |
231 | [super webView:view decidePolicyForNewWindowAction:action request:request newFrameName:frame decisionListener:mediator]; | |
232 | [mediator decide]; | |
233 | } | |
5d8f1006 | 234 | |
c2292b80 JF |
235 | - (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { |
236 | [[self delegate] webView:view didClearWindowObject:window forFrame:frame]; | |
237 | if ([super respondsToSelector:@selector(webView:didClearWindowObject:forFrame:)]) | |
238 | [super webView:view didClearWindowObject:window forFrame:frame]; | |
239 | } | |
d4f84362 | 240 | |
c2292b80 JF |
241 | - (void) webView:(WebView *)view didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { |
242 | [[self delegate] webView:view didFailLoadWithError:error forFrame:frame]; | |
243 | if ([super respondsToSelector:@selector(webView:didFailLoadWithError:forFrame:)]) | |
244 | [super webView:view didFailLoadWithError:error forFrame:frame]; | |
4825688a JF |
245 | } |
246 | ||
c2292b80 JF |
247 | - (void) webView:(WebView *)view didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { |
248 | [[self delegate] webView:view didFailProvisionalLoadWithError:error forFrame:frame]; | |
249 | if ([super respondsToSelector:@selector(webView:didFailProvisionalLoadWithError:forFrame:)]) | |
250 | [super webView:view didFailProvisionalLoadWithError:error forFrame:frame]; | |
251 | } | |
5a5c1e4b | 252 | |
c2292b80 JF |
253 | - (void) webView:(WebView *)view didFinishLoadForFrame:(WebFrame *)frame { |
254 | [[self delegate] webView:view didFinishLoadForFrame:frame]; | |
255 | if ([super respondsToSelector:@selector(webView:didFinishLoadForFrame:)]) | |
256 | [super webView:view didFinishLoadForFrame:frame]; | |
257 | } | |
bde2d79b | 258 | |
c2292b80 JF |
259 | - (void) webView:(WebView *)view didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { |
260 | [[self delegate] webView:view didReceiveTitle:title forFrame:frame]; | |
261 | if ([super respondsToSelector:@selector(webView:didReceiveTitle:forFrame:)]) | |
262 | [super webView:view didReceiveTitle:title forFrame:frame]; | |
263 | } | |
9d7f5e2d | 264 | |
c2292b80 JF |
265 | - (void) webView:(WebView *)view didStartProvisionalLoadForFrame:(WebFrame *)frame { |
266 | [[self delegate] webView:view didStartProvisionalLoadForFrame:frame]; | |
267 | if ([super respondsToSelector:@selector(webView:didStartProvisionalLoadForFrame:)]) | |
268 | [super webView:view didStartProvisionalLoadForFrame:frame]; | |
269 | } | |
bde2d79b | 270 | |
c2292b80 JF |
271 | - (NSURLRequest *) webView:(WebView *)view resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source { |
272 | if ([super respondsToSelector:@selector(webView:resource:willSendRequest:redirectResponse:)]) | |
273 | request = [super webView:view resource:identifier willSendRequest:request redirectResponse:response fromDataSource:source]; | |
274 | return [[self delegate] webView:view resource:identifier willSendRequest:request redirectResponse:response fromDataSource:source]; | |
275 | } | |
9d7f5e2d | 276 | |
c2292b80 JF |
277 | - (void) webView:(WebView *)view runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { |
278 | if ([super respondsToSelector:@selector(webView:runJavaScriptAlertPanelWithMessage:initiatedByFrame:)]) | |
279 | if ([[self delegate] webView:view shouldRunJavaScriptAlertPanelWithMessage:message initiatedByFrame:frame]) | |
280 | [super webView:view runJavaScriptAlertPanelWithMessage:message initiatedByFrame:frame]; | |
281 | } | |
bde2d79b | 282 | |
c2292b80 JF |
283 | - (BOOL) webView:(WebView *)view runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { |
284 | if ([super respondsToSelector:@selector(webView:runJavaScriptConfirmPanelWithMessage:initiatedByFrame:)]) | |
285 | if ([[self delegate] webView:view shouldRunJavaScriptConfirmPanelWithMessage:message initiatedByFrame:frame]) | |
286 | return [super webView:view runJavaScriptConfirmPanelWithMessage:message initiatedByFrame:frame]; | |
287 | return NO; | |
288 | } | |
d4f84362 | 289 | |
c2292b80 JF |
290 | - (NSString *) webView:(WebView *)view runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)text initiatedByFrame:(WebFrame *)frame { |
291 | if ([super respondsToSelector:@selector(webView:runJavaScriptTextInputPanelWithPrompt:defaultText:initiatedByFrame:)]) | |
292 | if ([[self delegate] webView:view shouldRunJavaScriptTextInputPanelWithPrompt:prompt defaultText:text initiatedByFrame:frame]) | |
293 | return [super webView:view runJavaScriptTextInputPanelWithPrompt:prompt defaultText:text initiatedByFrame:frame]; | |
294 | return nil; | |
295 | } | |
d4f84362 | 296 | |
c2292b80 JF |
297 | - (void) webViewClose:(WebView *)view { |
298 | [[self delegate] webViewClose:view]; | |
299 | if ([super respondsToSelector:@selector(webViewClose:)]) | |
300 | [super webViewClose:view]; | |
301 | } | |
bde2d79b | 302 | |
c2292b80 | 303 | @end |
9d7f5e2d | 304 | |
c2292b80 JF |
305 | #define ShowInternals 0 |
306 | #define LogBrowser 1 | |
bde2d79b | 307 | |
c2292b80 | 308 | #define lprintf(args...) fprintf(stderr, args) |
bde2d79b | 309 | |
c2292b80 JF |
310 | @implementation BrowserController |
311 | ||
312 | #if ShowInternals | |
313 | #include "UICaboodle/UCInternal.h" | |
bde2d79b JF |
314 | #endif |
315 | ||
c2292b80 JF |
316 | + (void) _initialize { |
317 | [WebPreferences _setInitialDefaultTextEncodingToSystemEncoding]; | |
318 | } | |
319 | ||
320 | - (void) dealloc { | |
321 | #if LogBrowser | |
322 | NSLog(@"[BrowserController dealloc]"); | |
323 | #endif | |
324 | ||
325 | [webview_ setDelegate:nil]; | |
326 | ||
327 | [indirect_ setDelegate:nil]; | |
bde2d79b JF |
328 | [indirect_ release]; |
329 | ||
c2292b80 JF |
330 | if (challenge_ != nil) |
331 | [challenge_ release]; | |
9d7f5e2d | 332 | |
c2292b80 | 333 | //NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; |
bde2d79b | 334 | |
c2292b80 JF |
335 | if (custom_ != nil) |
336 | [custom_ release]; | |
bde2d79b JF |
337 | if (style_ != nil) |
338 | [style_ release]; | |
c2292b80 | 339 | |
bde2d79b JF |
340 | if (function_ != nil) |
341 | [function_ release]; | |
1ce016d4 JF |
342 | if (closer_ != nil) |
343 | [closer_ release]; | |
bde2d79b | 344 | |
0fc560b6 JF |
345 | if (sensitive_ != nil) |
346 | [sensitive_ release]; | |
bde2d79b JF |
347 | if (title_ != nil) |
348 | [title_ release]; | |
c2292b80 JF |
349 | |
350 | [reloaditem_ release]; | |
351 | [loadingitem_ release]; | |
352 | ||
353 | [indicator_ release]; | |
f99f86e2 | 354 | |
bde2d79b JF |
355 | [super dealloc]; |
356 | } | |
357 | ||
358 | - (void) loadURL:(NSURL *)url cachePolicy:(NSURLRequestCachePolicy)policy { | |
359 | [self loadRequest:[NSURLRequest | |
360 | requestWithURL:url | |
361 | cachePolicy:policy | |
daf7f6e2 | 362 | timeoutInterval:120.0 |
bde2d79b JF |
363 | ]]; |
364 | } | |
365 | ||
366 | - (void) loadURL:(NSURL *)url { | |
367 | [self loadURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy]; | |
368 | } | |
369 | ||
bde2d79b | 370 | - (void) loadRequest:(NSURLRequest *)request { |
f4772bd1 | 371 | error_ = false; |
9d7f5e2d JF |
372 | |
373 | WebThreadLock(); | |
c2292b80 | 374 | [webview_ loadRequest:request]; |
9d7f5e2d | 375 | WebThreadUnlock(); |
bde2d79b JF |
376 | } |
377 | ||
378 | - (void) reloadURL { | |
bde2d79b JF |
379 | if (request_ == nil) |
380 | return; | |
381 | ||
382 | if ([request_ HTTPBody] == nil && [request_ HTTPBodyStream] == nil) | |
f4772bd1 | 383 | [self loadRequest:request_]; |
bde2d79b | 384 | else { |
afcd8bef | 385 | UIAlertView *alert = [[[UIAlertView alloc] |
61b13cae | 386 | initWithTitle:UCLocalize("RESUBMIT_FORM") |
afcd8bef | 387 | message:nil |
bde2d79b | 388 | delegate:self |
afcd8bef GP |
389 | cancelButtonTitle:UCLocalize("CANCEL") |
390 | otherButtonTitles:UCLocalize("SUBMIT"), nil | |
bde2d79b | 391 | ] autorelease]; |
c2292b80 | 392 | |
afcd8bef GP |
393 | [alert setContext:@"submit"]; |
394 | [alert show]; | |
bde2d79b JF |
395 | } |
396 | } | |
397 | ||
bde2d79b | 398 | - (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { |
c2292b80 JF |
399 | if (custom_ != nil) |
400 | [custom_ autorelease]; | |
401 | custom_ = button == nil ? nil : [[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:button]]] retain]; | |
bde2d79b JF |
402 | |
403 | if (style_ != nil) | |
404 | [style_ autorelease]; | |
405 | style_ = style == nil ? nil : [style retain]; | |
406 | ||
407 | if (function_ != nil) | |
408 | [function_ autorelease]; | |
409 | function_ = function == nil ? nil : [function retain]; | |
1ce016d4 | 410 | |
f99f86e2 | 411 | [self applyRightButton]; |
bde2d79b JF |
412 | } |
413 | ||
414 | - (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { | |
c2292b80 JF |
415 | if (custom_ != nil) |
416 | [custom_ autorelease]; | |
417 | custom_ = button == nil ? nil : [button retain]; | |
bde2d79b JF |
418 | |
419 | if (style_ != nil) | |
420 | [style_ autorelease]; | |
421 | style_ = style == nil ? nil : [style retain]; | |
422 | ||
423 | if (function_ != nil) | |
424 | [function_ autorelease]; | |
425 | function_ = function == nil ? nil : [function retain]; | |
1ce016d4 | 426 | |
f99f86e2 | 427 | [self applyRightButton]; |
bde2d79b | 428 | } |
bde2d79b | 429 | |
9d7f5e2d JF |
430 | - (void) setPopupHook:(id)function { |
431 | if (closer_ != nil) | |
432 | [closer_ autorelease]; | |
433 | closer_ = function == nil ? nil : [function retain]; | |
434 | } | |
435 | ||
c2292b80 JF |
436 | - (void) setViewportWidth:(float)width { |
437 | width_ = width != 0 ? width : [[self class] defaultWidth]; | |
438 | [[webview_ _documentView] setViewportSize:CGSizeMake(width_, UIWebViewGrowsAndShrinksToFitHeight) forDocumentTypes:0x10]; | |
bde2d79b JF |
439 | } |
440 | ||
c2292b80 JF |
441 | - (void) _openMailToURL:(NSURL *)url { |
442 | [[UIApplication sharedApplication] openURL:url];// asPanel:YES]; | |
bde2d79b JF |
443 | } |
444 | ||
c2292b80 JF |
445 | - (bool) _allowJavaScriptPanel { |
446 | return true; | |
bde2d79b JF |
447 | } |
448 | ||
c2292b80 JF |
449 | - (void) _didFailWithError:(NSError *)error forFrame:(WebFrame *)frame { |
450 | [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]]; | |
451 | [self _didFinishLoading]; | |
bde2d79b | 452 | |
c2292b80 | 453 | if ([error code] == NSURLErrorCancelled) |
bde2d79b JF |
454 | return; |
455 | ||
9d7f5e2d | 456 | if ([frame parentFrame] == nil) { |
c2292b80 JF |
457 | [self loadURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?%@", |
458 | [[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"error" ofType:@"html"]] absoluteString], | |
459 | [[error localizedDescription] stringByAddingPercentEscapes] | |
460 | ]]]; | |
bde2d79b | 461 | |
c2292b80 JF |
462 | error_ = true; |
463 | } | |
464 | } | |
9d7f5e2d | 465 | |
c2292b80 JF |
466 | // CYWebViewDelegate {{{ |
467 | - (void) webView:(WebView *)view decidePolicyForNavigationAction:(NSDictionary *)action request:(NSURLRequest *)request frame:(WebFrame *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { | |
468 | #if LogBrowser | |
469 | NSLog(@"decidePolicyForNavigationAction:%@ request:%@ frame:%@", action, request, frame); | |
470 | #endif | |
d4f84362 | 471 | |
c2292b80 JF |
472 | if (!error_ && [frame parentFrame] == nil) { |
473 | if (request_ != nil) | |
474 | [request_ autorelease]; | |
475 | if (request == nil) | |
476 | request_ = nil; | |
d4f84362 | 477 | else |
c2292b80 | 478 | request_ = [request retain]; |
9d7f5e2d | 479 | } |
bde2d79b JF |
480 | } |
481 | ||
c2292b80 JF |
482 | - (void) webView:(WebView *)view decidePolicyForNewWindowAction:(NSDictionary *)action request:(NSURLRequest *)request newFrameName:(NSString *)frame decisionListener:(id<WebPolicyDecisionListener>)listener { |
483 | #if LogBrowser | |
484 | NSLog(@"decidePolicyForNewWindowAction:%@ request:%@ newFrameName:%@", action, request, frame); | |
485 | #endif | |
c8e3b4b3 | 486 | |
c2292b80 JF |
487 | NSURL *url([request URL]); |
488 | if (url == nil) | |
489 | return; | |
f99f86e2 | 490 | |
c2292b80 JF |
491 | if ([frame isEqualToString:@"_open"]) |
492 | [delegate_ openURL:url]; | |
c8e3b4b3 | 493 | |
c2292b80 JF |
494 | NSString *scheme([[url scheme] lowercaseString]); |
495 | if ([scheme isEqualToString:@"mailto"]) | |
496 | [self _openMailToURL:url]; | |
3db9f43c | 497 | |
c2292b80 | 498 | CYViewController *page([delegate_ pageForURL:url hasTag:NULL]); |
b36becfc | 499 | |
c2292b80 JF |
500 | if (page == nil) { |
501 | BrowserController *browser([[[class_ alloc] init] autorelease]); | |
502 | [browser loadRequest:request]; | |
503 | page = browser; | |
f99f86e2 | 504 | } |
161c1078 | 505 | |
c2292b80 | 506 | [page setDelegate:delegate_]; |
9ae52960 | 507 | |
c2292b80 JF |
508 | if (![frame isEqualToString:@"_popup"]) { |
509 | [[self navigationItem] setTitle:title_]; | |
9ae52960 | 510 | |
c2292b80 JF |
511 | [[self navigationController] pushViewController:page animated:YES]; |
512 | } else { | |
513 | UCNavigationController *navigation([[[UCNavigationController alloc] init] autorelease]); | |
bde2d79b | 514 | |
c2292b80 JF |
515 | [navigation setHook:indirect_]; |
516 | [navigation setDelegate:delegate_]; | |
bde2d79b | 517 | |
c2292b80 JF |
518 | [navigation setViewControllers:[NSArray arrayWithObject:page]]; |
519 | ||
520 | [[page navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] | |
521 | initWithTitle:UCLocalize("CLOSE") | |
522 | style:UIBarButtonItemStylePlain | |
523 | target:page | |
524 | action:@selector(close) | |
525 | ] autorelease]]; | |
526 | ||
527 | [[self navigationController] presentModalViewController:navigation animated:YES]; | |
528 | } | |
bde2d79b | 529 | |
c2292b80 | 530 | [listener ignore]; |
bde2d79b JF |
531 | } |
532 | ||
c2292b80 | 533 | - (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { |
bde2d79b JF |
534 | } |
535 | ||
c2292b80 JF |
536 | - (void) webView:(WebView *)view didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { |
537 | #if LogBrowser | |
538 | NSLog(@"didFailLoadWithError:%@ forFrame:%@", error, frame); | |
539 | #endif | |
540 | ||
541 | [self _didFailWithError:error forFrame:frame]; | |
bde2d79b JF |
542 | } |
543 | ||
c2292b80 JF |
544 | - (void) webView:(WebView *)view didFailProvisionalLoadWithError:(NSError *)error forFrame:(WebFrame *)frame { |
545 | #if LogBrowser | |
546 | NSLog(@"didFailProvisionalLoadWithError:%@ forFrame:%@", error, frame); | |
547 | #endif | |
548 | ||
549 | [self _didFailWithError:error forFrame:frame]; | |
bde2d79b JF |
550 | } |
551 | ||
c2292b80 | 552 | - (void) webView:(WebView *)view didFinishLoadForFrame:(WebFrame *)frame { |
b452841e | 553 | [loading_ removeObject:[NSValue valueWithNonretainedObject:frame]]; |
bde2d79b | 554 | |
9d7f5e2d | 555 | if ([frame parentFrame] == nil) { |
bde2d79b JF |
556 | if (DOMDocument *document = [frame DOMDocument]) |
557 | if (DOMNodeList<NSFastEnumeration> *bodies = [document getElementsByTagName:@"body"]) | |
485f16d6 | 558 | for (DOMHTMLBodyElement *body in (id) bodies) { |
bde2d79b JF |
559 | DOMCSSStyleDeclaration *style([document getComputedStyle:body pseudoElement:nil]); |
560 | ||
561 | bool colored(false); | |
562 | ||
563 | if (DOMCSSPrimitiveValue *color = static_cast<DOMCSSPrimitiveValue *>([style getPropertyCSSValue:@"background-color"])) { | |
f4772bd1 JF |
564 | if ([color primitiveType] == DOM_CSS_RGBCOLOR) { |
565 | DOMRGBColor *rgb([color getRGBColorValue]); | |
566 | ||
567 | float red([[rgb red] getFloatValue:DOM_CSS_NUMBER]); | |
568 | float green([[rgb green] getFloatValue:DOM_CSS_NUMBER]); | |
569 | float blue([[rgb blue] getFloatValue:DOM_CSS_NUMBER]); | |
570 | float alpha([[rgb alpha] getFloatValue:DOM_CSS_NUMBER]); | |
571 | ||
572 | UIColor *uic(nil); | |
573 | ||
574 | if (red == 0xc7 && green == 0xce && blue == 0xd5) | |
aaa0be19 | 575 | uic = [UIColor groupTableViewBackgroundColor]; |
f4772bd1 JF |
576 | else if (alpha != 0) |
577 | uic = [UIColor | |
578 | colorWithRed:(red / 255) | |
579 | green:(green / 255) | |
580 | blue:(blue / 255) | |
581 | alpha:alpha | |
582 | ]; | |
583 | ||
584 | if (uic != nil) { | |
585 | colored = true; | |
586 | [scroller_ setBackgroundColor:uic]; | |
587 | } | |
bde2d79b JF |
588 | } |
589 | } | |
590 | ||
591 | if (!colored) | |
aaa0be19 | 592 | [scroller_ setBackgroundColor:[UIColor groupTableViewBackgroundColor]]; |
bde2d79b JF |
593 | break; |
594 | } | |
595 | } | |
596 | ||
c2292b80 | 597 | [self _didFinishLoading]; |
bde2d79b JF |
598 | } |
599 | ||
c2292b80 JF |
600 | - (void) webView:(WebView *)view didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame { |
601 | if ([frame parentFrame] != nil) | |
602 | return; | |
9d7f5e2d | 603 | |
c2292b80 JF |
604 | title_ = [title retain]; |
605 | [[self navigationItem] setTitle:title_]; | |
606 | } | |
bde2d79b | 607 | |
c2292b80 JF |
608 | - (void) webView:(WebView *)view didStartProvisionalLoadForFrame:(WebFrame *)frame { |
609 | [loading_ addObject:[NSValue valueWithNonretainedObject:frame]]; | |
b452841e | 610 | |
9d7f5e2d | 611 | if ([frame parentFrame] == nil) { |
c2292b80 JF |
612 | CYRelease(title_); |
613 | CYRelease(custom_); | |
614 | CYRelease(style_); | |
615 | CYRelease(function_); | |
616 | CYRelease(closer_); | |
617 | ||
618 | // XXX: do we still need to do this? | |
619 | [[self navigationItem] setTitle:nil]; | |
9d7f5e2d | 620 | } |
f4772bd1 | 621 | |
c2292b80 | 622 | [self _didStartLoading]; |
9d7f5e2d JF |
623 | } |
624 | ||
c2292b80 JF |
625 | - (NSURLRequest *) webView:(WebView *)view resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source { |
626 | return request; | |
bde2d79b JF |
627 | } |
628 | ||
c2292b80 JF |
629 | - (bool) webView:(WebView *)view shouldRunJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { |
630 | return [self _allowJavaScriptPanel]; | |
bde2d79b JF |
631 | } |
632 | ||
c2292b80 JF |
633 | - (bool) webView:(WebView *)view shouldRunJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame { |
634 | return [self _allowJavaScriptPanel]; | |
d4f84362 JF |
635 | } |
636 | ||
c2292b80 JF |
637 | - (bool) webView:(WebView *)view shouldRunJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)text initiatedByFrame:(WebFrame *)frame { |
638 | return [self _allowJavaScriptPanel]; | |
d4f84362 JF |
639 | } |
640 | ||
c2292b80 JF |
641 | - (void) webViewClose:(WebView *)view { |
642 | [self close]; | |
d4f84362 | 643 | } |
c2292b80 | 644 | // }}} |
d4f84362 | 645 | |
c2292b80 JF |
646 | - (void) close { |
647 | [[self navigationController] dismissModalViewControllerAnimated:YES]; | |
d4f84362 JF |
648 | } |
649 | ||
c2292b80 JF |
650 | - (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button { |
651 | NSString *context([alert context]); | |
d4f84362 | 652 | |
c2292b80 JF |
653 | if ([context isEqualToString:@"sensitive"]) { |
654 | switch (button) { | |
655 | case 1: | |
656 | sensitive_ = [NSNumber numberWithBool:YES]; | |
657 | break; | |
d4f84362 | 658 | |
c2292b80 JF |
659 | case 2: |
660 | sensitive_ = [NSNumber numberWithBool:NO]; | |
661 | break; | |
662 | } | |
d4f84362 | 663 | |
c2292b80 JF |
664 | [alert dismissWithClickedButtonIndex:-1 animated:YES]; |
665 | } else if ([context isEqualToString:@"challenge"]) { | |
666 | id<NSURLAuthenticationChallengeSender> sender([challenge_ sender]); | |
9d7f5e2d | 667 | |
c2292b80 JF |
668 | switch (button) { |
669 | case 1: { | |
670 | NSString *username([[alert textFieldAtIndex:0] text]); | |
671 | NSString *password([[alert textFieldAtIndex:1] text]); | |
d4f84362 | 672 | |
c2292b80 | 673 | NSURLCredential *credential([NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistenceForSession]); |
d4f84362 | 674 | |
c2292b80 JF |
675 | [sender useCredential:credential forAuthenticationChallenge:challenge_]; |
676 | } break; | |
d4f84362 | 677 | |
c2292b80 JF |
678 | case 2: |
679 | [sender cancelAuthenticationChallenge:challenge_]; | |
680 | break; | |
d4f84362 | 681 | |
c2292b80 JF |
682 | _nodefault |
683 | } | |
d4f84362 | 684 | |
c2292b80 JF |
685 | [challenge_ release]; |
686 | challenge_ = nil; | |
d4f84362 | 687 | |
c2292b80 JF |
688 | [alert dismissWithClickedButtonIndex:-1 animated:YES]; |
689 | } else if ([context isEqualToString:@"submit"]) { | |
690 | switch (button) { | |
691 | case 1: | |
692 | break; | |
d4f84362 | 693 | |
c2292b80 JF |
694 | case 2: |
695 | if (request_ != nil) { | |
696 | WebThreadLock(); | |
697 | [webview_ loadRequest:request_]; | |
698 | WebThreadUnlock(); | |
699 | } | |
700 | break; | |
d4f84362 | 701 | |
c2292b80 JF |
702 | _nodefault |
703 | } | |
d4f84362 | 704 | |
c2292b80 JF |
705 | [alert dismissWithClickedButtonIndex:-1 animated:YES]; |
706 | } | |
d4f84362 JF |
707 | } |
708 | ||
c2292b80 JF |
709 | - (UIBarButtonItemStyle) rightButtonStyle { |
710 | if (style_ == nil) normal: | |
711 | return UIBarButtonItemStylePlain; | |
712 | else if ([style_ isEqualToString:@"Normal"]) | |
713 | return UIBarButtonItemStylePlain; | |
714 | else if ([style_ isEqualToString:@"Highlighted"]) | |
715 | return UIBarButtonItemStyleDone; | |
716 | else goto normal; | |
d4f84362 JF |
717 | } |
718 | ||
c2292b80 JF |
719 | - (UIBarButtonItem *) customButton { |
720 | return [[[UIBarButtonItem alloc] | |
721 | initWithTitle:custom_ | |
722 | style:[self rightButtonStyle] | |
723 | target:self | |
724 | action:@selector(customButtonClicked) | |
725 | ] autorelease]; | |
9d7f5e2d JF |
726 | } |
727 | ||
c2292b80 JF |
728 | - (UIBarButtonItem *) rightButton { |
729 | return reloaditem_; | |
dcc55b8b JF |
730 | } |
731 | ||
c2292b80 JF |
732 | - (void) applyLoadingTitle { |
733 | [[self navigationItem] setTitle:UCLocalize("LOADING")]; | |
9d7f5e2d JF |
734 | } |
735 | ||
c2292b80 JF |
736 | - (void) applyRightButton { |
737 | if ([self isLoading]) { | |
738 | [[self navigationItem] setRightBarButtonItem:loadingitem_ animated:YES]; | |
739 | // XXX: why do we do this again here? | |
740 | [[loadingitem_ view] addSubview:indicator_]; | |
741 | [self applyLoadingTitle]; | |
742 | } else if (custom_ != nil) { | |
743 | [[self navigationItem] setRightBarButtonItem:[self customButton] animated:YES]; | |
744 | } else { | |
745 | [[self navigationItem] setRightBarButtonItem:[self rightButton] animated:YES]; | |
746 | } | |
9d7f5e2d JF |
747 | } |
748 | ||
c2292b80 JF |
749 | - (void) _didStartLoading { |
750 | [self applyRightButton]; | |
9d7f5e2d JF |
751 | } |
752 | ||
c2292b80 JF |
753 | - (void) _didFinishLoading { |
754 | if ([loading_ count] != 0) | |
755 | return; | |
756 | ||
757 | [self applyRightButton]; | |
758 | ||
759 | // XXX: wtf? | |
760 | if (![self isLoading]) | |
761 | [[self navigationItem] setTitle:title_]; | |
9d7f5e2d JF |
762 | } |
763 | ||
c2292b80 JF |
764 | - (bool) isLoading { |
765 | return [loading_ count] != 0; | |
9d7f5e2d JF |
766 | } |
767 | ||
9ae52960 GP |
768 | - (id) initWithWidth:(float)width ofClass:(Class)_class { |
769 | if ((self = [super init]) != nil) { | |
85021801 | 770 | class_ = _class; |
c2292b80 | 771 | loading_ = [[NSMutableSet alloc] initWithCapacity:5]; |
f99f86e2 | 772 | |
c2292b80 | 773 | indirect_ = [[IndirectDelegate alloc] initWithDelegate:self]; |
9d7f5e2d | 774 | |
c2292b80 JF |
775 | webview_ = [[[CYWebView alloc] initWithFrame:[[self view] bounds]] autorelease]; |
776 | [webview_ setDelegate:self]; | |
777 | [self setView:webview_]; | |
bde2d79b | 778 | |
c2292b80 JF |
779 | if ([webview_ respondsToSelector:@selector(setDataDetectorTypes:)]) |
780 | [webview_ setDataDetectorTypes:UIDataDetectorTypeAutomatic]; | |
781 | else | |
782 | [webview_ setDetectsPhoneNumbers:NO]; | |
bde2d79b | 783 | |
c2292b80 | 784 | [webview_ setScalesPageToFit:YES]; |
bde2d79b | 785 | |
c2292b80 | 786 | UIWebDocumentView *document([webview_ _documentView]); |
4825688a | 787 | |
c2292b80 JF |
788 | // XXX: I think this improves scrolling; the hardcoded-ness sucks |
789 | [document setTileSize:CGSizeMake(320, 500)]; | |
4825688a | 790 | |
c2292b80 JF |
791 | [document setBackgroundColor:[UIColor clearColor]]; |
792 | [document setDrawsBackground:NO]; | |
4825688a | 793 | |
c2292b80 JF |
794 | WebView *webview([document webView]); |
795 | WebPreferences *preferences([webview preferences]); | |
bde2d79b | 796 | |
c2292b80 JF |
797 | // XXX: I have no clue if I actually /want/ this modification |
798 | if ([webview respondsToSelector:@selector(_setLayoutInterval:)]) | |
799 | [webview _setLayoutInterval:0]; | |
800 | else if ([preferences respondsToSelector:@selector(_setLayoutInterval:)]) | |
801 | [preferences _setLayoutInterval:0]; | |
bde2d79b | 802 | |
c2292b80 JF |
803 | [preferences setCacheModel:WebCacheModelDocumentBrowser]; |
804 | [preferences setOfflineWebApplicationCacheEnabled:YES]; | |
bde2d79b | 805 | |
c2292b80 JF |
806 | if ([webview_ respondsToSelector:@selector(_scrollView)]) { |
807 | scroller_ = [webview_ _scrollView]; | |
bde2d79b | 808 | |
c2292b80 JF |
809 | [scroller_ setDirectionalLockEnabled:YES]; |
810 | [scroller_ setDecelerationRate:UIScrollViewDecelerationRateNormal]; | |
811 | [scroller_ setDelaysContentTouches:NO]; | |
bde2d79b | 812 | |
c2292b80 JF |
813 | [scroller_ setCanCancelContentTouches:YES]; |
814 | } else if ([webview_ respondsToSelector:@selector(_scroller)]) { | |
815 | UIScroller *scroller([webview_ _scroller]); | |
816 | scroller_ = (UIScrollView *) scroller; | |
bde2d79b | 817 | |
c2292b80 JF |
818 | [scroller setDirectionalScrolling:YES]; |
819 | [scroller setScrollDecelerationFactor:UIScrollViewDecelerationRateNormal]; /* 0.989324 */ | |
820 | [scroller setScrollHysteresis:0]; /* 8 */ | |
7b00c562 | 821 | |
c2292b80 | 822 | [scroller setThumbDetectionEnabled:NO]; |
4825688a | 823 | |
c2292b80 JF |
824 | // use NO with UIApplicationUseLegacyEvents(YES) |
825 | [scroller setEventMode:YES]; | |
4825688a | 826 | |
c2292b80 JF |
827 | // XXX: this is handled by setBounces, right? |
828 | //[scroller setAllowsRubberBanding:YES]; | |
bde2d79b | 829 | } |
f99f86e2 | 830 | |
c2292b80 JF |
831 | [scroller_ setFixedBackgroundPattern:YES]; |
832 | [scroller_ setBackgroundColor:[UIColor groupTableViewBackgroundColor]]; | |
833 | [scroller_ setClipsSubviews:YES]; | |
9d7f5e2d | 834 | |
c2292b80 JF |
835 | [scroller_ setBounces:YES]; |
836 | [scroller_ setScrollingEnabled:YES]; | |
837 | [scroller_ setShowBackgroundShadow:NO]; | |
9d7f5e2d | 838 | |
c2292b80 | 839 | [self setViewportWidth:width]; |
f99f86e2 JF |
840 | |
841 | reloaditem_ = [[UIBarButtonItem alloc] | |
842 | initWithTitle:UCLocalize("RELOAD") | |
843 | style:[self rightButtonStyle] | |
844 | target:self | |
845 | action:@selector(reloadButtonClicked) | |
846 | ]; | |
847 | ||
848 | loadingitem_ = [[UIBarButtonItem alloc] | |
849 | initWithTitle:@" " | |
850 | style:UIBarButtonItemStylePlain | |
851 | target:self | |
852 | action:@selector(reloadButtonClicked) | |
853 | ]; | |
c2292b80 JF |
854 | |
855 | CGSize indsize = [UIProgressIndicator defaultSizeForStyle:UIProgressIndicatorStyleMediumWhite]; | |
856 | indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(15, 5, indsize.width, indsize.height)]; | |
857 | [indicator_ setStyle:UIProgressIndicatorStyleMediumWhite]; | |
858 | [indicator_ startAnimation]; | |
f99f86e2 | 859 | [[loadingitem_ view] addSubview:indicator_]; |
bde2d79b | 860 | |
c2292b80 | 861 | [webview_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; |
d3bef7bc | 862 | [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; |
bde2d79b JF |
863 | } return self; |
864 | } | |
865 | ||
9ae52960 GP |
866 | - (id) initWithWidth:(float)width { |
867 | return [self initWithWidth:width ofClass:[self class]]; | |
85021801 JF |
868 | } |
869 | ||
9ae52960 GP |
870 | - (id) init { |
871 | return [self initWithWidth:0]; | |
7b00c562 JF |
872 | } |
873 | ||
c2292b80 JF |
874 | - (void) didDismissModalViewController { |
875 | if (closer_ != nil) | |
876 | [self callFunction:closer_]; | |
bde2d79b JF |
877 | } |
878 | ||
1ce016d4 | 879 | - (void) callFunction:(WebScriptObject *)function { |
9d7f5e2d JF |
880 | WebThreadLock(); |
881 | ||
c2292b80 | 882 | WebView *webview([[webview_ _documentView] webView]); |
1ce016d4 | 883 | WebFrame *frame([webview mainFrame]); |
1e4922b8 JF |
884 | WebPreferences *preferences([webview preferences]); |
885 | ||
886 | bool maybe([preferences javaScriptCanOpenWindowsAutomatically]); | |
887 | [preferences setJavaScriptCanOpenWindowsAutomatically:NO]; | |
bde2d79b | 888 | |
1e4922b8 | 889 | /*id _private(MSHookIvar<id>(webview, "_private")); |
1ce016d4 JF |
890 | WebCore::Page *page(_private == nil ? NULL : MSHookIvar<WebCore::Page *>(_private, "page")); |
891 | WebCore::Settings *settings(page == NULL ? NULL : page->settings()); | |
bde2d79b | 892 | |
1ce016d4 JF |
893 | bool no; |
894 | if (settings == NULL) | |
895 | no = 0; | |
896 | else { | |
897 | no = settings->JavaScriptCanOpenWindowsAutomatically(); | |
898 | settings->setJavaScriptCanOpenWindowsAutomatically(true); | |
1e4922b8 | 899 | }*/ |
1ce016d4 | 900 | |
9ae52960 | 901 | if (UIWindow *window = [[self view] window]) |
61b13cae JF |
902 | if (UIResponder *responder = [window firstResponder]) |
903 | [responder resignFirstResponder]; | |
904 | ||
1ce016d4 JF |
905 | JSObjectRef object([function JSObject]); |
906 | JSGlobalContextRef context([frame globalContext]); | |
907 | JSObjectCallAsFunction(context, object, NULL, 0, NULL, NULL); | |
908 | ||
1e4922b8 JF |
909 | /*if (settings != NULL) |
910 | settings->setJavaScriptCanOpenWindowsAutomatically(no);*/ | |
911 | ||
912 | [preferences setJavaScriptCanOpenWindowsAutomatically:maybe]; | |
9d7f5e2d JF |
913 | |
914 | WebThreadUnlock(); | |
1ce016d4 JF |
915 | } |
916 | ||
161c1078 | 917 | - (void) reloadButtonClicked { |
1ce016d4 JF |
918 | [self reloadURL]; |
919 | } | |
920 | ||
b98e849f DH |
921 | - (void) _customButtonClicked { |
922 | [self reloadButtonClicked]; | |
923 | } | |
924 | ||
161c1078 | 925 | - (void) customButtonClicked { |
9d7f5e2d JF |
926 | #if !AlwaysReload |
927 | if (function_ != nil) | |
1ce016d4 | 928 | [self callFunction:function_]; |
9d7f5e2d JF |
929 | else |
930 | #endif | |
b98e849f | 931 | [self _customButtonClicked]; |
bde2d79b JF |
932 | } |
933 | ||
7b00c562 JF |
934 | + (float) defaultWidth { |
935 | return 980; | |
936 | } | |
937 | ||
3db9f43c | 938 | @end |