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