tizen beta release
[profile/ivi/webkit-efl.git] / Tools / MiniBrowser / mac / BrowserWindowController.m
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "BrowserWindowController.h"
27
28 #import <WebKit2/WKPagePrivate.h>
29 #import <WebKit2/WKStringCF.h>
30 #import <WebKit2/WKURLCF.h>
31 #import <WebKit2/WKViewPrivate.h>
32
33 @interface BrowserWindowController ()
34 - (void)didStartProgress;
35 - (void)didChangeProgress:(double)value;
36 - (void)didFinishProgress;
37 - (void)didStartProvisionalLoadForFrame:(WKFrameRef)frame;
38 - (void)didCommitLoadForFrame:(WKFrameRef)frame;
39 - (void)didReceiveServerRedirectForProvisionalLoadForFrame:(WKFrameRef)frame;
40 - (void)didFailProvisionalLoadWithErrorForFrame:(WKFrameRef)frame;
41 - (void)didFailLoadWithErrorForFrame:(WKFrameRef)frame;
42 - (void)didSameDocumentNavigationForFrame:(WKFrameRef)frame;
43 @end
44
45 @implementation BrowserWindowController
46
47 - (id)initWithContext:(WKContextRef)context pageGroup:(WKPageGroupRef)pageGroup
48 {
49     if ((self = [super initWithWindowNibName:@"BrowserWindow"])) {
50         _context = WKRetain(context);
51         _pageGroup = WKRetain(pageGroup);
52         _zoomTextOnly = NO;
53     }
54     
55     return self;
56 }
57
58 - (void)dealloc
59 {
60     assert(!_context);
61     [super dealloc];
62 }
63
64 - (IBAction)fetch:(id)sender
65 {
66     CFURLRef cfURL = CFURLCreateWithString(0, (CFStringRef)[urlText stringValue], 0);
67     if (!cfURL)
68         return;
69
70     WKURLRef url = WKURLCreateWithCFURL(cfURL);
71     CFRelease(cfURL);
72
73     WKPageLoadURL(_webView.pageRef, url);
74     WKRelease(url);
75 }
76
77 - (IBAction)showHideWebView:(id)sender
78 {
79     BOOL hidden = ![_webView isHidden];
80     
81     [_webView setHidden:hidden];
82 }
83
84 - (IBAction)removeReinsertWebView:(id)sender
85 {
86     if ([_webView window]) {
87         [_webView retain];
88         [_webView removeFromSuperview]; 
89     } else {
90         [containerView addSubview:_webView];
91         [_webView release];
92     }
93 }
94
95 - (BOOL)validateMenuItem:(NSMenuItem *)menuItem
96 {
97     SEL action = [menuItem action];
98
99     if (action == @selector(zoomIn:))
100         return [self canZoomIn];
101     if (action == @selector(zoomOut:))
102         return [self canZoomOut];
103     if (action == @selector(resetZoom:))
104         return [self canResetZoom];
105
106     if (action == @selector(showHideWebView:))
107         [menuItem setTitle:[_webView isHidden] ? @"Show Web View" : @"Hide Web View"];
108     else if (action == @selector(removeReinsertWebView:))
109         [menuItem setTitle:[_webView window] ? @"Remove Web View" : @"Insert Web View"];
110     else if (action == @selector(toggleZoomMode:))
111         [menuItem setState:_zoomTextOnly ? NSOnState : NSOffState];
112     return YES;
113 }
114
115 - (IBAction)reload:(id)sender
116 {
117     WKPageReload(_webView.pageRef);
118 }
119
120 - (IBAction)forceRepaint:(id)sender
121 {
122     [_webView setNeedsDisplay:YES];
123 }
124
125 - (IBAction)goBack:(id)sender
126 {
127     WKPageGoBack(_webView.pageRef);
128 }
129
130 - (IBAction)goForward:(id)sender
131 {
132     WKPageGoForward(_webView.pageRef);
133 }
134
135 - (BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item
136 {
137     SEL action = [item action];
138
139     if (action == @selector(goBack:))
140         return _webView && WKPageCanGoBack(_webView.pageRef);
141     
142     if (action == @selector(goForward:))
143         return _webView && WKPageCanGoForward(_webView.pageRef);
144     
145     return YES;
146 }
147
148 - (void)validateToolbar
149 {
150     [toolbar validateVisibleItems];
151 }
152
153 - (BOOL)windowShouldClose:(id)sender
154 {
155     LOG(@"windowShouldClose");
156     BOOL canCloseImmediately = WKPageTryClose(_webView.pageRef);
157     return canCloseImmediately;
158 }
159
160 - (void)windowWillClose:(NSNotification *)notification
161 {
162     WKRelease(_context);
163     _context = 0;
164     WKRelease(_pageGroup);
165     _pageGroup = 0;
166 }
167
168 - (void)applicationTerminating
169 {
170     WKPageClose(_webView.pageRef);
171     WKRelease(_webView.pageRef);
172 }
173
174 #define DefaultMinimumZoomFactor (.5)
175 #define DefaultMaximumZoomFactor (3.0)
176 #define DefaultZoomFactorRatio (1.2)
177
178 - (double)currentZoomFactor
179 {
180     return _zoomTextOnly ? WKPageGetTextZoomFactor(_webView.pageRef) : WKPageGetPageZoomFactor(_webView.pageRef);
181 }
182
183 - (void)setCurrentZoomFactor:(double)factor
184 {
185     _zoomTextOnly ? WKPageSetTextZoomFactor(_webView.pageRef, factor) : WKPageSetPageZoomFactor(_webView.pageRef, factor);
186 }
187
188 - (BOOL)canZoomIn
189 {
190     return [self currentZoomFactor] * DefaultZoomFactorRatio < DefaultMaximumZoomFactor;
191 }
192
193 - (void)zoomIn:(id)sender
194 {
195     if (![self canZoomIn])
196         return;
197
198     double factor = [self currentZoomFactor] * DefaultZoomFactorRatio;
199     [self setCurrentZoomFactor:factor];
200 }
201
202 - (BOOL)canZoomOut
203 {
204     return [self currentZoomFactor] / DefaultZoomFactorRatio > DefaultMinimumZoomFactor;
205 }
206
207 - (void)zoomOut:(id)sender
208 {
209     if (![self canZoomIn])
210         return;
211
212     double factor = [self currentZoomFactor] / DefaultZoomFactorRatio;
213     [self setCurrentZoomFactor:factor];
214 }
215
216 - (BOOL)canResetZoom
217 {
218     return _zoomTextOnly ? (WKPageGetTextZoomFactor(_webView.pageRef) != 1) : (WKPageGetPageZoomFactor(_webView.pageRef) != 1);
219 }
220
221 - (void)resetZoom:(id)sender
222 {
223     if (![self canResetZoom])
224         return;
225
226     if (_zoomTextOnly)
227         WKPageSetTextZoomFactor(_webView.pageRef, 1);
228     else
229         WKPageSetPageZoomFactor(_webView.pageRef, 1);
230 }
231
232 - (IBAction)toggleZoomMode:(id)sender
233 {
234     if (_zoomTextOnly) {
235         _zoomTextOnly = NO;
236         double currentTextZoom = WKPageGetTextZoomFactor(_webView.pageRef);
237         WKPageSetPageAndTextZoomFactors(_webView.pageRef, currentTextZoom, 1);
238     } else {
239         _zoomTextOnly = YES;
240         double currentPageZoom = WKPageGetPageZoomFactor(_webView.pageRef);
241         WKPageSetPageAndTextZoomFactors(_webView.pageRef, 1, currentPageZoom);
242     }
243 }
244
245 - (IBAction)dumpSourceToConsole:(id)sender
246 {
247     WKPageGetSourceForFrame_b(_webView.pageRef, WKPageGetMainFrame(_webView.pageRef), ^(WKStringRef result, WKErrorRef error) {
248         CFStringRef cfResult = WKStringCopyCFString(0, result);
249         LOG(@"Main frame source\n \"%@\"", (NSString *)cfResult);
250         CFRelease(cfResult);
251     });
252 }
253
254 // MARK: Loader Client Callbacks
255
256 static void didStartProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
257 {
258     [(BrowserWindowController *)clientInfo didStartProvisionalLoadForFrame:frame];
259 }
260
261 static void didReceiveServerRedirectForProvisionalLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
262 {
263     [(BrowserWindowController *)clientInfo didReceiveServerRedirectForProvisionalLoadForFrame:frame];
264 }
265
266 static void didFailProvisionalLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo)
267 {
268     [(BrowserWindowController *)clientInfo didFailProvisionalLoadWithErrorForFrame:frame];
269 }
270
271 static void didCommitLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
272 {
273     [(BrowserWindowController *)clientInfo didCommitLoadForFrame:frame];
274 }
275
276 static void didFinishDocumentLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
277 {
278     LOG(@"didFinishDocumentLoadForFrame");
279 }
280
281 static void didFinishLoadForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
282 {
283     LOG(@"didFinishLoadForFrame");
284 }
285
286 static void didFailLoadWithErrorForFrame(WKPageRef page, WKFrameRef frame, WKErrorRef error, WKTypeRef userData, const void *clientInfo)
287 {
288     [(BrowserWindowController *)clientInfo didFailLoadWithErrorForFrame:frame];
289 }
290
291 static void didSameDocumentNavigationForFrame(WKPageRef page, WKFrameRef frame, WKSameDocumentNavigationType type, WKTypeRef userData, const void *clientInfo)
292 {
293     [(BrowserWindowController *)clientInfo didSameDocumentNavigationForFrame:frame];
294 }
295
296 static void didReceiveTitleForFrame(WKPageRef page, WKStringRef title, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
297 {
298     CFStringRef cfTitle = WKStringCopyCFString(0, title);
299     LOG(@"didReceiveTitleForFrame \"%@\"", (NSString *)cfTitle);
300     CFRelease(cfTitle);
301 }
302
303 static void didFirstLayoutForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
304 {
305     LOG(@"didFirstLayoutForFrame");
306 }
307
308 static void didFirstVisuallyNonEmptyLayoutForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
309 {
310     LOG(@"didFirstVisuallyNonEmptyLayoutForFrame");
311 }
312
313 static void didRemoveFrameFromHierarchy(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
314 {
315     LOG(@"didRemoveFrameFromHierarchy");
316 }
317
318 static void didDisplayInsecureContentForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
319 {
320     LOG(@"didDisplayInsecureContentForFrame");
321 }
322
323 static void didRunInsecureContentForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo)
324 {
325     LOG(@"didRunInsecureContentForFrame");
326 }
327
328 static void didDetectXSSForFrame(WKPageRef page, WKFrameRef frame, WKTypeRef userData, const void *clientInfo) 
329
330     LOG(@"didDetectXSSForFrame"); 
331 }
332  
333 static void didStartProgress(WKPageRef page, const void *clientInfo)
334 {
335     [(BrowserWindowController *)clientInfo didStartProgress];
336 }
337
338 static void didChangeProgress(WKPageRef page, const void *clientInfo)
339 {
340     [(BrowserWindowController *)clientInfo didChangeProgress:WKPageGetEstimatedProgress(page)];
341 }
342
343 static void didFinishProgress(WKPageRef page, const void *clientInfo)
344 {
345     [(BrowserWindowController *)clientInfo didFinishProgress];
346 }
347
348 static void didBecomeUnresponsive(WKPageRef page, const void *clientInfo)
349 {
350     LOG(@"didBecomeUnresponsive");
351 }
352
353 static void didBecomeResponsive(WKPageRef page, const void *clientInfo)
354 {
355     LOG(@"didBecomeResponsive");
356 }
357
358 static void processDidExit(WKPageRef page, const void *clientInfo)
359 {
360     LOG(@"processDidExit");
361 }
362
363 static void didChangeBackForwardList(WKPageRef page, WKBackForwardListItemRef addedItem, WKArrayRef removedItems, const void *clientInfo)
364 {
365     [(BrowserWindowController *)clientInfo validateToolbar];
366 }
367
368 // MARK: Policy Client Callbacks
369
370 static void decidePolicyForNavigationAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
371 {
372     LOG(@"decidePolicyForNavigationAction");
373     WKFramePolicyListenerUse(listener);
374 }
375
376 static void decidePolicyForNewWindowAction(WKPageRef page, WKFrameRef frame, WKFrameNavigationType navigationType, WKEventModifiers modifiers, WKEventMouseButton mouseButton, WKURLRequestRef request, WKStringRef frameName, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
377 {
378     LOG(@"decidePolicyForNewWindowAction");
379     WKFramePolicyListenerUse(listener);
380 }
381
382 static void decidePolicyForResponse(WKPageRef page, WKFrameRef frame, WKURLResponseRef response, WKURLRequestRef request, WKFramePolicyListenerRef listener, WKTypeRef userData, const void* clientInfo)
383 {
384     WKFramePolicyListenerUse(listener);
385 }
386
387 // MARK: UI Client Callbacks
388
389 static WKPageRef createNewPage(WKPageRef page, WKURLRequestRef request, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton button, const void* clientInfo)
390 {
391     LOG(@"createNewPage");
392     BrowserWindowController *controller = [[BrowserWindowController alloc] initWithContext:WKPageGetContext(page) pageGroup:WKPageGetPageGroup(page)];
393     [controller loadWindow];
394
395     return controller->_webView.pageRef;
396 }
397
398 static void showPage(WKPageRef page, const void *clientInfo)
399 {
400     LOG(@"showPage");
401     [[(BrowserWindowController *)clientInfo window] orderFront:nil];
402 }
403
404 static void closePage(WKPageRef page, const void *clientInfo)
405 {
406     LOG(@"closePage");
407     WKPageClose(page);
408     [[(BrowserWindowController *)clientInfo window] close];
409     WKRelease(page);
410 }
411
412 static void runJavaScriptAlert(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
413 {
414     NSAlert* alert = [[NSAlert alloc] init];
415
416     WKURLRef wkURL = WKFrameCopyURL(frame);
417     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
418     WKRelease(wkURL);
419
420     [alert setMessageText:[NSString stringWithFormat:@"JavaScript alert dialog from %@.", [(NSURL *)cfURL absoluteString]]];
421     CFRelease(cfURL);
422
423     CFStringRef cfMessage = WKStringCopyCFString(0, message);
424     [alert setInformativeText:(NSString *)cfMessage];
425     CFRelease(cfMessage);
426
427     [alert addButtonWithTitle:@"OK"];
428
429     [alert runModal];
430     [alert release];
431 }
432
433 static bool runJavaScriptConfirm(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
434 {
435     NSAlert* alert = [[NSAlert alloc] init];
436
437     WKURLRef wkURL = WKFrameCopyURL(frame);
438     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
439     WKRelease(wkURL);
440
441     [alert setMessageText:[NSString stringWithFormat:@"JavaScript confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]];
442     CFRelease(cfURL);
443
444     CFStringRef cfMessage = WKStringCopyCFString(0, message);
445     [alert setInformativeText:(NSString *)cfMessage];
446     CFRelease(cfMessage);
447
448     [alert addButtonWithTitle:@"OK"];
449     [alert addButtonWithTitle:@"Cancel"];
450
451     NSInteger button = [alert runModal];
452     [alert release];
453
454     return button == NSAlertFirstButtonReturn;
455 }
456
457 static WKStringRef runJavaScriptPrompt(WKPageRef page, WKStringRef message, WKStringRef defaultValue, WKFrameRef frame, const void* clientInfo)
458 {
459     NSAlert* alert = [[NSAlert alloc] init];
460
461     WKURLRef wkURL = WKFrameCopyURL(frame);
462     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
463     WKRelease(wkURL);
464
465     [alert setMessageText:[NSString stringWithFormat:@"JavaScript prompt dialog from %@.", [(NSURL *)cfURL absoluteString]]];
466     CFRelease(cfURL);
467
468     CFStringRef cfMessage = WKStringCopyCFString(0, message);
469     [alert setInformativeText:(NSString *)cfMessage];
470     CFRelease(cfMessage);
471
472     [alert addButtonWithTitle:@"OK"];
473     [alert addButtonWithTitle:@"Cancel"];
474
475     NSTextField* input = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 200, 24)];
476     CFStringRef cfDefaultValue = WKStringCopyCFString(0, defaultValue);
477     [input setStringValue:(NSString *)cfDefaultValue];
478     CFRelease(cfDefaultValue);
479
480     [alert setAccessoryView:input];
481
482     NSInteger button = [alert runModal];
483
484     NSString* result = nil;
485     if (button == NSAlertFirstButtonReturn) {
486         [input validateEditing];
487         result = [input stringValue];
488     }
489
490     [alert release];
491
492     if (!result)
493         return 0;
494     return WKStringCreateWithCFString((CFStringRef)result);
495 }
496
497 static void setStatusText(WKPageRef page, WKStringRef text, const void* clientInfo)
498 {
499     LOG(@"setStatusText");
500 }
501
502 static void mouseDidMoveOverElement(WKPageRef page, WKHitTestResultRef hitTestResult, WKEventModifiers modifiers, WKTypeRef userData, const void *clientInfo)
503 {
504     LOG(@"mouseDidMoveOverElement");
505 }
506
507 static WKRect getWindowFrame(WKPageRef page, const void* clientInfo)
508 {
509     NSRect rect = [[(BrowserWindowController *)clientInfo window] frame];
510     WKRect wkRect;
511     wkRect.origin.x = rect.origin.x;
512     wkRect.origin.y = rect.origin.y;
513     wkRect.size.width = rect.size.width;
514     wkRect.size.height = rect.size.height;
515     return wkRect;
516 }
517
518 static void setWindowFrame(WKPageRef page, WKRect rect, const void* clientInfo)
519 {
520     [[(BrowserWindowController *)clientInfo window] setFrame:NSMakeRect(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height) display:YES];
521 }
522
523 static bool runBeforeUnloadConfirmPanel(WKPageRef page, WKStringRef message, WKFrameRef frame, const void* clientInfo)
524 {
525     NSAlert *alert = [[NSAlert alloc] init];
526
527     WKURLRef wkURL = WKFrameCopyURL(frame);
528     CFURLRef cfURL = WKURLCopyCFURL(0, wkURL);
529     WKRelease(wkURL);
530
531     [alert setMessageText:[NSString stringWithFormat:@"BeforeUnload confirm dialog from %@.", [(NSURL *)cfURL absoluteString]]];
532     CFRelease(cfURL);
533
534     CFStringRef cfMessage = WKStringCopyCFString(0, message);
535     [alert setInformativeText:(NSString *)cfMessage];
536     CFRelease(cfMessage);
537
538     [alert addButtonWithTitle:@"OK"];
539     [alert addButtonWithTitle:@"Cancel"];
540
541     NSInteger button = [alert runModal];
542     [alert release];
543
544     return button == NSAlertFirstButtonReturn;
545 }
546
547 static void runOpenPanel(WKPageRef page, WKFrameRef frame, WKOpenPanelParametersRef parameters, WKOpenPanelResultListenerRef listener, const void* clientInfo)
548 {
549     NSOpenPanel *openPanel = [NSOpenPanel openPanel];
550     [openPanel setAllowsMultipleSelection:WKOpenPanelParametersGetAllowsMultipleFiles(parameters)];
551
552     WKRetain(listener);
553
554     [openPanel beginSheetModalForWindow:[(BrowserWindowController *)clientInfo window] completionHandler:^(NSInteger result) {
555         if (result == NSFileHandlingPanelOKButton) {
556             WKMutableArrayRef fileURLs = WKMutableArrayCreate();
557
558             NSURL *nsURL;
559             for (nsURL in [openPanel URLs]) {
560                 WKURLRef wkURL = WKURLCreateWithCFURL((CFURLRef)nsURL);
561                 WKArrayAppendItem(fileURLs, wkURL);
562                 WKRelease(wkURL);
563             }
564
565             WKOpenPanelResultListenerChooseFiles(listener, fileURLs);
566
567             WKRelease(fileURLs);
568         } else
569             WKOpenPanelResultListenerCancel(listener);
570         
571         WKRelease(listener);
572     }];
573 }
574
575 - (void)awakeFromNib
576 {
577     _webView = [[WKView alloc] initWithFrame:[containerView frame] contextRef:_context pageGroupRef:_pageGroup];
578
579     [containerView addSubview:_webView];
580     [_webView setFrame:[containerView frame]];
581     
582     [_webView setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
583     
584     WKPageLoaderClient loadClient = {
585         kWKPageLoaderClientCurrentVersion,
586         self,   /* clientInfo */
587         didStartProvisionalLoadForFrame,
588         didReceiveServerRedirectForProvisionalLoadForFrame,
589         didFailProvisionalLoadWithErrorForFrame,
590         didCommitLoadForFrame,
591         didFinishDocumentLoadForFrame,
592         didFinishLoadForFrame,
593         didFailLoadWithErrorForFrame,
594         didSameDocumentNavigationForFrame,
595         didReceiveTitleForFrame,
596         didFirstLayoutForFrame,
597         didFirstVisuallyNonEmptyLayoutForFrame,
598         didRemoveFrameFromHierarchy,
599         didDisplayInsecureContentForFrame,
600         didRunInsecureContentForFrame,
601         0, // canAuthenticateAgainstProtectionSpaceInFrame
602         0, // didReceiveAuthenticationChallengeInFrame
603         didStartProgress,
604         didChangeProgress,
605         didFinishProgress,
606         didBecomeUnresponsive,
607         didBecomeResponsive,
608         processDidExit,
609         didChangeBackForwardList,
610         0, // shouldGoToBackForwardItem
611         0,  // didFailToInitializePlugin
612         didDetectXSSForFrame,
613     };
614     WKPageSetPageLoaderClient(_webView.pageRef, &loadClient);
615     
616     WKPagePolicyClient policyClient = {
617         kWKPagePolicyClientCurrentVersion,
618         self,       /* clientInfo */
619         decidePolicyForNavigationAction,
620         decidePolicyForNewWindowAction,
621         decidePolicyForResponse,
622         0           /* unableToImplementPolicy */
623     };
624     WKPageSetPagePolicyClient(_webView.pageRef, &policyClient);
625
626     WKPageUIClient uiClient = {
627         kWKPageUIClientCurrentVersion,
628         self,       /* clientInfo */
629         0,          /* createNewPage_deprecatedForUseWithV0 */
630         showPage,
631         closePage,
632         0,          /* takeFocus */
633         0,          /* focus */
634         0,          /* unfocus */
635         runJavaScriptAlert,
636         runJavaScriptConfirm,
637         runJavaScriptPrompt,
638         setStatusText,
639         0,          /* mouseDidMoveOverElement_deprecatedForUseWithV0 */
640         0,          /* missingPluginButtonClicked */
641         0,          /* didNotHandleKeyEvent */
642         0,          /* didNotHandleWheelEvent */
643         0,          /* toolbarsAreVisible */
644         0,          /* setToolbarsAreVisible */
645         0,          /* menuBarIsVisible */
646         0,          /* setMenuBarIsVisible */
647         0,          /* statusBarIsVisible */
648         0,          /* setStatusBarIsVisible */
649         0,          /* isResizable */
650         0,          /* setIsResizable */
651         getWindowFrame,
652         setWindowFrame,
653         runBeforeUnloadConfirmPanel,
654         0,          /* didDraw */
655         0,          /* pageDidScroll */
656         0,          /* exceededDatabaseQuota */
657         runOpenPanel,
658         0,          /* decidePolicyForGeolocationPermissionRequest */
659         0, // headerHeight
660         0, // footerHeight
661         0, // drawHeader
662         0, // drawFooter
663         0, // printFrame
664         0, // showModal
665         0, // didCompleteRubberBandForMainFrame
666         0, // saveDataToFileInDownloadsFolder
667         0, // shouldInterruptJavaScript
668         createNewPage,
669         mouseDidMoveOverElement,
670     };
671     WKPageSetPageUIClient(_webView.pageRef, &uiClient);
672 }
673
674 - (void)didStartProgress
675 {
676     [progressIndicator setDoubleValue:0.0];
677     [progressIndicator setHidden:NO];
678 }
679
680 - (void)didChangeProgress:(double)value
681 {
682     [progressIndicator setDoubleValue:value];
683 }
684
685 - (void)didFinishProgress
686 {
687     [progressIndicator setHidden:YES];
688     [progressIndicator setDoubleValue:1.0];
689 }
690
691 - (void)updateProvisionalURLForFrame:(WKFrameRef)frame
692 {
693     static WKURLRef emptyURL = 0;
694     if (!emptyURL)
695         emptyURL = WKURLCreateWithUTF8CString("");
696
697     WKURLRef url = WKFrameCopyProvisionalURL(frame);
698
699     if (!url)
700         return;
701
702     if (WKURLIsEqual(url, emptyURL)) {
703         WKRelease(url);
704         return;
705     }
706
707     CFURLRef cfSourceURL = WKURLCopyCFURL(0, url);
708     WKRelease(url);
709
710     [urlText setStringValue:(NSString*)CFURLGetString(cfSourceURL)];
711     CFRelease(cfSourceURL);
712 }
713
714 - (void)didStartProvisionalLoadForFrame:(WKFrameRef)frame
715 {
716     if (!WKFrameIsMainFrame(frame))
717         return;
718
719     [self updateProvisionalURLForFrame:frame];
720 }
721
722 - (void)didReceiveServerRedirectForProvisionalLoadForFrame:(WKFrameRef)frame
723 {
724     if (!WKFrameIsMainFrame(frame))
725         return;
726
727     [self updateProvisionalURLForFrame:frame];
728 }
729
730 - (void)didFailProvisionalLoadWithErrorForFrame:(WKFrameRef)frame
731 {
732     if (!WKFrameIsMainFrame(frame))
733         return;
734
735     [self updateProvisionalURLForFrame:frame];
736 }
737
738 - (void)didFailLoadWithErrorForFrame:(WKFrameRef)frame
739 {
740     if (!WKFrameIsMainFrame(frame))
741         return;
742
743     [self updateProvisionalURLForFrame:frame];
744 }
745
746 - (void)didSameDocumentNavigationForFrame:(WKFrameRef)frame
747 {
748 }
749
750 - (void)didCommitLoadForFrame:(WKFrameRef)frame
751 {
752 }
753
754 - (void)loadURLString:(NSString *)urlString
755 {
756     // FIXME: We shouldn't have to set the url text here.
757     [urlText setStringValue:urlString];
758     [self fetch:nil];
759 }
760
761 - (IBAction)performFindPanelAction:(id)sender
762 {
763     [findPanelWindow makeKeyAndOrderFront:sender];
764 }
765
766 - (IBAction)find:(id)sender
767 {
768     WKStringRef string = WKStringCreateWithCFString((CFStringRef)[sender stringValue]);
769
770     WKPageFindString(_webView.pageRef, string, kWKFindOptionsCaseInsensitive | kWKFindOptionsWrapAround | kWKFindOptionsShowFindIndicator | kWKFindOptionsShowOverlay, 100);
771 }
772
773 @end